master
Ethan Dalool 2016-12-22 19:42:21 -08:00
parent 6e64483523
commit 0896ba96e6
20 changed files with 1826 additions and 1269 deletions

View File

@ -9,10 +9,24 @@ import os
from voussoirkit import bytestring
# 128 bits
BLOCK_SIZE = 32
KEY_SIZE = 32
SEEK_END = 2
def decrypt_data(aes, data):
data = aes.decrypt(data)
pad_byte = data[-1:]
data = data.rstrip(pad_byte)
return data
def encrypt_data(aes, data):
pad_byte = (data[-1] + 1) % 256
pad_length = BLOCK_SIZE - (len(data) % BLOCK_SIZE)
data += (bytes([pad_byte]) * pad_length)
data = aes.encrypt(data)
return data
def decrypt_file(aes, input_handle, output_handle):
current_pos = input_handle.tell()
input_size = input_handle.seek(0, SEEK_END) - current_pos
@ -42,8 +56,7 @@ def encrypt_file(aes, input_handle, output_handle):
last_byte = chunk[-1]
if len(chunk) < BLOCK_SIZE:
pad_byte = (last_byte + 1) % 256
pad_byte = chr(pad_byte)
pad_byte = pad_byte.encode('ascii')
pad_byte = bytes([pad_byte])
chunk += pad_byte * (BLOCK_SIZE - len(chunk))
done = True
bytes_read += len(chunk)
@ -60,7 +73,7 @@ def encrypt_argparse(args):
input_handle = open(args.input, 'rb')
output_handle = open(args.output, 'wb')
password = hashit(args.password, 32)
password = hashit(args.password)
initialization_vector = os.urandom(16)
aes = AES.new(password, mode=3, IV=initialization_vector)
output_handle.write(initialization_vector)
@ -71,15 +84,14 @@ def decrypt_argparse(args):
input_handle = open(args.input, 'rb')
output_handle = open(args.output, 'wb')
password = hashit(args.password, 32)
password = hashit(args.password)
initialization_vector = input_handle.read(16)
aes = AES.new(password, mode=3, IV=initialization_vector)
decrypt_file(aes, input_handle, output_handle)
def hashit(text, length=None):
def hashit(text):
h = hashlib.sha512(text.encode('utf-8')).hexdigest()
if length is not None:
h = h[:length]
h = h[:BLOCK_SIZE]
return h
def main(argv):
@ -102,4 +114,4 @@ def main(argv):
args.func(args)
if __name__ == '__main__':
main(sys.argv[1:])
main(sys.argv[1:])

View File

@ -23,7 +23,7 @@ FILENAME_BADCHARS = '*?"<>|\r'
last_request = 0
CHUNKSIZE = 4 * bytestring.KIBIBYTE
TIMEOUT = 600
TIMEOUT = 60
TEMP_EXTENSION = '.downloadytemp'
PRINT_LIMITER = ratelimiter.Ratelimiter(allowance=5, mode='reject')
@ -35,11 +35,12 @@ def download_file(
auth=None,
bytespersecond=None,
callback_progress=None,
do_head=True,
headers=None,
overwrite=False,
raise_for_undersized=True,
timeout=None,
verbose=False,
**get_kwargs
):
headers = headers or {}
@ -61,13 +62,20 @@ def download_file(
localname,
auth=auth,
bytespersecond=bytespersecond,
callback_progress=callback_progress,
do_head=do_head,
headers=headers,
overwrite=overwrite,
raise_for_undersized=raise_for_undersized,
timeout=timeout,
)
#print(plan)
if plan is None:
return
return download_plan(plan)
def download_plan(plan):
localname = plan['download_into']
directory = os.path.split(localname)[0]
if directory != '':
@ -77,7 +85,7 @@ def download_file(
file_handle.seek(plan['seek_to'])
if plan['header_range_min'] is not None:
headers['range'] = 'bytes={min}-{max}'.format(
plan['headers']['range'] = 'bytes={min}-{max}'.format(
min=plan['header_range_min'],
max=plan['header_range_max'],
)
@ -89,7 +97,20 @@ def download_file(
else:
bytes_downloaded = 0
download_stream = request('get', url, stream=True, headers=headers, auth=auth, **get_kwargs)
download_stream = request(
'get',
plan['url'],
stream=True,
auth=plan['auth'],
headers=plan['headers'],
timeout=plan['timeout'],
)
if plan['remote_total_bytes'] is None:
# Since we didn't do a head, let's fill this in now.
plan['remote_total_bytes'] = int(download_stream.headers.get('Content-Length', 0))
callback_progress = plan['callback_progress']
if callback_progress is not None:
callback_progress = callback_progress(plan['remote_total_bytes'])
@ -108,7 +129,7 @@ def download_file(
if os.devnull not in [localname, plan['real_localname']]:
localsize = os.path.getsize(localname)
undersized = plan['plan_type'] != 'partial' and localsize < plan['remote_total_bytes']
if raise_for_undersized and undersized:
if plan['raise_for_undersized'] and undersized:
message = 'File does not contain expected number of bytes. Received {size} / {total}'
message = message.format(size=localsize, total=plan['remote_total_bytes'])
raise Exception(message)
@ -121,12 +142,17 @@ def download_file(
def prepare_plan(
url,
localname,
auth,
bytespersecond,
headers,
overwrite,
auth=None,
bytespersecond=None,
callback_progress=None,
do_head=True,
headers=None,
overwrite=False,
raise_for_undersized=True,
timeout=TIMEOUT,
):
# Chapter 1: File existence
headers = headers or {}
user_provided_range = 'range' in headers
real_localname = localname
temp_localname = localname + TEMP_EXTENSION
@ -163,21 +189,34 @@ def prepare_plan(
temp_headers = headers
temp_headers.update({'range': 'bytes=0-'})
# I'm using a GET instead of an actual HEAD here because some servers respond
# differently, even though they're not supposed to.
head = request('get', url, stream=True, headers=temp_headers, auth=auth)
remote_total_bytes = int(head.headers.get('content-length', 0))
server_respects_range = (head.status_code == 206 and 'content-range' in head.headers)
head.connection.close()
if do_head:
# I'm using a GET instead of an actual HEAD here because some servers respond
# differently, even though they're not supposed to.
head = request('get', url, stream=True, headers=temp_headers, auth=auth)
remote_total_bytes = int(head.headers.get('content-length', 0))
server_respects_range = (head.status_code == 206 and 'content-range' in head.headers)
head.connection.close()
else:
remote_total_bytes = None
server_respects_range = False
if user_provided_range and not server_respects_range:
raise Exception('Server did not respect your range header')
if not do_head:
raise Exception('Cannot determine range support without the head request')
else:
raise Exception('Server did not respect your range header')
# Chapter 5: Plan definitions
plan_base = {
'url': url,
'auth': auth,
'callback_progress': callback_progress,
'limiter': limiter,
'headers': headers,
'real_localname': real_localname,
'raise_for_undersized': raise_for_undersized,
'remote_total_bytes': remote_total_bytes,
'timeout': timeout,
}
plan_fulldownload = dict(
plan_base,
@ -373,8 +412,10 @@ def download_argparse(args):
localname=args.localname,
bytespersecond=bytespersecond,
callback_progress=callback,
do_head=args.no_head is False,
headers=headers,
overwrite=args.overwrite,
timeout=int(args.timeout),
verbose=True,
)
@ -388,6 +429,8 @@ if __name__ == '__main__':
parser.add_argument('-bps', '--bytespersecond', dest='bytespersecond', default=None)
parser.add_argument('-ow', '--overwrite', dest='overwrite', action='store_true')
parser.add_argument('-r', '--range', dest='range', default=None)
parser.add_argument('--timeout', dest='timeout', default=TIMEOUT)
parser.add_argument('--no-head', dest='no_head', action='store_true')
parser.set_defaults(func=download_argparse)
args = parser.parse_args()

View File

@ -1,25 +1,25 @@
import glob
import os
class Path:
'''
I started to use pathlib.Path, but it was too much of a pain.
'''
def __init__(self, path):
path = os.path.normpath(path)
path = os.path.abspath(path)
self.absolute_path = path
if isinstance(path, Path):
self.absolute_path = path.absolute_path
else:
path = os.path.normpath(path)
path = os.path.abspath(path)
self.absolute_path = path
def __contains__(self, other):
this = os.path.normcase(self.absolute_path)
that = os.path.normcase(other.absolute_path)
return that.startswith(this)
return other.normcase.startswith(self.normcase)
def __eq__(self, other):
if not hasattr(other, 'absolute_path'):
return False
this = os.path.normcase(self.absolute_path)
that = os.path.normcase(other.absolute_path)
return this == that
return self.normcase == other.normcase
def __hash__(self):
return hash(os.path.normcase(self.absolute_path))
@ -35,6 +35,10 @@ class Path:
self.absolute_path = get_path_casing(self.absolute_path)
return self.absolute_path
@property
def depth(self):
return len(self.absolute_path.split(os.sep))
@property
def exists(self):
return os.path.exists(self.absolute_path)
@ -51,6 +55,10 @@ class Path:
def is_link(self):
return os.path.islink(self.absolute_path)
@property
def normcase(self):
return os.path.normcase(self.absolute_path)
@property
def parent(self):
parent = os.path.dirname(self.absolute_path)
@ -59,10 +67,21 @@ class Path:
@property
def relative_path(self):
relative = self.absolute_path
relative = relative.replace(os.getcwd(), '')
relative = relative.lstrip(os.sep)
return relative
cwd = Path(os.getcwd())
self.correct_case()
if self.absolute_path == cwd:
return '.'
if self in cwd:
return self.absolute_path.replace(cwd.absolute_path, '.')
common = common_path([os.getcwd(), self.absolute_path], fallback=None)
if common is None:
return self.absolute_path
backsteps = cwd.depth - common.depth
backsteps = os.sep.join('..' for x in range(backsteps))
print('hi')
return self.absolute_path.replace(common.absolute_path, backsteps)
@property
def size(self):
@ -80,6 +99,34 @@ class Path:
return Path(os.path.join(self.absolute_path, basename))
def common_path(paths, fallback):
'''
Given a list of file paths, determine the deepest path which all
have in common.
'''
if isinstance(paths, (str, Path)):
raise TypeError('`paths` must be a collection')
paths = [Path(f) for f in paths]
if len(paths) == 0:
raise ValueError('Empty list')
if hasattr(paths, 'pop'):
model = paths.pop()
else:
model = paths[0]
paths = paths[1:]
while True:
if all(f in model for f in paths):
return model
parent = model.parent
if parent == model:
# We just processed the root, and now we're stuck at the root.
# Which means there was no common path.
return fallback
model = parent
def get_path_casing(path):
'''
Take what is perhaps incorrectly cased input and get the path's actual
@ -89,8 +136,21 @@ def get_path_casing(path):
Ethan Furman http://stackoverflow.com/a/7133137/5430534
xvorsx http://stackoverflow.com/a/14742779/5430534
'''
if isinstance(path, Path):
path = path.absolute_path
if not isinstance(path, Path):
path = Path(path)
# Nonexistent paths don't glob correctly. If the input is a nonexistent
# subpath of an existing path, we have to glob the existing portion first,
# and then attach the fake portion again at the end.
input_path = path
while not path.exists:
parent = path.parent
if path == parent:
# We're stuck at a fake root.
return input_path.absolute_path
path = parent
path = path.absolute_path
(drive, subpath) = os.path.splitdrive(path)
drive = drive.upper()
@ -99,11 +159,17 @@ def get_path_casing(path):
pattern = [glob_patternize(piece) for piece in subpath.split(os.sep)]
pattern = os.sep.join(pattern)
pattern = drive + os.sep + pattern
#print(pattern)
try:
return glob.glob(pattern)[0]
cased = glob.glob(pattern)[0]
imaginary_portion = input_path.normcase
real_portion = os.path.normcase(cased)
imaginary_portion = imaginary_portion.replace(real_portion, '')
imaginary_portion = imaginary_portion.lstrip(os.sep)
cased = os.path.join(cased, imaginary_portion)
return cased
except IndexError:
return path
return input_path
def glob_patternize(piece):
'''
@ -111,10 +177,15 @@ def glob_patternize(piece):
correct path name, while guaranteeing that the only result will be the correct path.
Special cases are:
!, because in glob syntax, [!x] tells glob to look for paths that don't contain
"x". [!] is invalid syntax, so we pick the first non-! character to put
in the brackets.
[, because this starts a capture group
`!`
because in glob syntax, [!x] tells glob to look for paths that don't contain
"x", and [!] is invalid syntax.
`[`, `]`
because this starts a glob capture group
so we pick the first non-special character to put in the brackets.
If the path consists entirely of these special characters, then the
casing doesn't need to be corrected anyway.
'''
piece = glob.escape(piece)
for character in piece:
@ -124,3 +195,13 @@ def glob_patternize(piece):
piece = piece.replace(character, replacement, 1)
break
return piece
def normalize_sep(path):
for char in ('\\', '/'):
if char != os.sep:
path = path.replace(char, os.sep)
path = path.rstrip(os.sep)
return path
def system_root():
return os.path.abspath(os.sep)

18
Safeprint/safeprint.py Normal file
View File

@ -0,0 +1,18 @@
'''
This function is slow and ugly, but I need a way to safely print unicode strings
on systems that don't support it without crippling those who do.
'''
def safeprint(text, file_handle=None):
for character in text:
try:
if file_handle:
file_handle.write(character)
else:
print(character, end='', flush=False)
except UnicodeError:
if file_handle:
file_handle.write('?')
else:
print('?', end='', flush=False)
if not file_handle:
print()

View File

@ -290,7 +290,7 @@ def generate_random_filename(original_filename='', length=8):
return identifier
def main():
server = ThreadedServer(('', 32768), RequestHandler)
server = ThreadedServer(('', int(sys.argv[1] or 32768)), RequestHandler)
print('server starting')
server.serve_forever()

File diff suppressed because it is too large Load Diff

22
Templates/timetest.py Normal file
View File

@ -0,0 +1,22 @@
import time
LOOPS = 10000
def func_1():
pass
def func_2():
pass
start = time.time()
for x in range(LOOPS):
func_1()
end = time.time()
print('v1', end - start)
start = time.time()
for x in range(LOOPS):
func_2()
end = time.time()
print('v2', end - start)

View File

@ -36,6 +36,10 @@ def threaded_dl(urls, thread_count, filename_format=None):
if filename_format is None:
filename_format = '{now}_{index}_{basename}'
filename_format = filename_format.replace('{index}', '{index:0%0dd}' % index_digits)
if '{' not in filename_format and len(urls) > 1:
filename_format += '_{index}'
if '{extension}' not in filename_format:
filename_format += '{extension}'
now = int(time.time())
for (index, url) in enumerate(urls):
while len(threads) == thread_count:

View File

@ -16,6 +16,8 @@ import random
import re
import sys
from voussoirkit import safeprint
def brename(transformation):
old = os.listdir()
@ -46,7 +48,7 @@ def loop(pairs, dry=False):
line = '{old}\n{new}\n'
line = line.format(old=x, new=y)
#print(line.encode('utf-8'))
print(line.encode('ascii', 'replace').decode())
safeprint.safeprint(line)
has_content = True
else:
os.rename(x, y)

View File

@ -10,6 +10,7 @@ import glob
import re
import sys
from voussoirkit import safeprint
from voussoirkit import spinal
filepattern = sys.argv[1]
@ -31,5 +32,5 @@ for filename in spinal.walk_generator():
pass
if matches:
print(filename)
print('\n'.join(matches).encode('ascii', 'replace').decode())
safeprint.safeprint('\n'.join(matches))
print()

View File

@ -5,14 +5,16 @@ import glob
import os
import sys
from voussoirkit import safeprint
def touch(glob_pattern):
filenames = glob.glob(glob_pattern)
if len(filenames) == 0:
print(glob_pattern.encode('ascii', 'replace').decode())
safeprint.safeprint(glob_pattern)
open(glob_pattern, 'a').close()
else:
for filename in filenames:
print(filename.encode('ascii', 'replace').decode())
safeprint.safeprint(filename)
os.utime(filename)
if __name__ == '__main__':

Binary file not shown.

After

Width:  |  Height:  |  Size: 168 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 168 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 168 B

View File

@ -0,0 +1,274 @@
import argparse
import math
import PIL.Image
import PIL.ImageDraw
import sys
def choose_guideline_style(guideline_mod):
if guideline_mod % 16 == 0:
return ('#1f32ff', 3)
if guideline_mod % 8 == 0:
return ('#80f783', 2)
if guideline_mod % 4 == 0:
return ('#f4bffb', 1)
def voxelspheregenerator(WIDTH, HEIGH, DEPTH, WALL_THICKNESS=None):
def in_ellipsoid(x, y, z, rad_x, rad_y, rad_z, center_x=None, center_y=None, center_z=None):
'''
Given a point (x, y, z), return whether that point lies inside the
ellipsoid defined by (x/a)^2 + (y/b)^2 + (z/c)^2 = 1
'''
if center_x is None: center_x = rad_x
if center_y is None: center_y = rad_y
if center_z is None: center_z = rad_z
#print(x, y, z, rad_x, rad_y, rad_z, center_x, center_y, center_z)
x = ((x - center_x) / rad_x) ** 2
y = ((y - center_y) / rad_y) ** 2
z = ((z - center_z) / rad_z) ** 2
distance = x + y + z
#print(distance)
return distance < 1
ODD_W = WIDTH % 2 == 1
ODD_H = HEIGH % 2 == 1
ODD_D = DEPTH % 2 == 1
RAD_X = WIDTH / 2
RAD_Y = HEIGH / 2
RAD_Z = DEPTH / 2
if WALL_THICKNESS:
INNER_RAD_X = RAD_X - WALL_THICKNESS
INNER_RAD_Y = RAD_Y - WALL_THICKNESS
INNER_RAD_Z = RAD_Z - WALL_THICKNESS
X_CENTER = {WIDTH // 2} if ODD_W else {WIDTH // 2, (WIDTH // 2) - 1}
Y_CENTER = {HEIGH // 2} if ODD_H else {HEIGH // 2, (HEIGH // 2) - 1}
Z_CENTER = {DEPTH // 2} if ODD_D else {DEPTH // 2, (DEPTH // 2) - 1}
layer_digits = len(str(DEPTH))
filename_form = '{w}x{h}x{d}w{wall}-{{layer:0{digits}}}.png'
filename_form = filename_form.format(
w=WIDTH,
h=HEIGH,
d=DEPTH,
wall=WALL_THICKNESS if WALL_THICKNESS else 0,
digits=layer_digits,
)
dot_highlight = PIL.Image.open('dot_highlight.png')
dot_normal = PIL.Image.open('dot_normal.png')
dot_corner = PIL.Image.open('dot_corner.png')
pixel_scale = dot_highlight.size[0]
# Space between each pixel
PIXEL_MARGIN = 7
# Space between the pixel area and the canvas
PIXELSPACE_MARGIN = 20
# Space between the canvas area and the image edge
CANVAS_MARGIN = 20
LABEL_HEIGH = 20
FINAL_IMAGE_SCALE = 1
PIXELSPACE_WIDTH = (WIDTH * pixel_scale) + ((WIDTH - 1) * PIXEL_MARGIN)
PIXELSPACE_HEIGH = (HEIGH * pixel_scale) + ((HEIGH - 1) * PIXEL_MARGIN)
CANVAS_WIDTH = PIXELSPACE_WIDTH + (2 * PIXELSPACE_MARGIN)
CANVAS_HEIGH = PIXELSPACE_HEIGH + (2 * PIXELSPACE_MARGIN)
IMAGE_WIDTH = CANVAS_WIDTH + (2 * CANVAS_MARGIN)
IMAGE_HEIGH = CANVAS_HEIGH + (2 * CANVAS_MARGIN) + LABEL_HEIGH
CANVAS_START_X = CANVAS_MARGIN
CANVAS_START_Y = CANVAS_MARGIN
CANVAS_END_X = CANVAS_START_X + CANVAS_WIDTH
CANVAS_END_Y = CANVAS_START_Y + CANVAS_HEIGH
PIXELSPACE_START_X = CANVAS_START_X + PIXELSPACE_MARGIN
PIXELSPACE_START_Y = CANVAS_START_Y + PIXELSPACE_MARGIN
PIXELSPACE_END_X = PIXELSPACE_START_X + PIXELSPACE_WIDTH
PIXELSPACE_END_Y = PIXELSPACE_START_Y + PIXELSPACE_HEIGH
GUIDELINE_MOD_X = math.ceil(RAD_X)
GUIDELINE_MOD_Y = math.ceil(RAD_Y)
def pixel_coord(x, y):
x = PIXELSPACE_START_X + (x * pixel_scale) + (x * PIXEL_MARGIN)
y = PIXELSPACE_START_Y + (y * pixel_scale) + (y * PIXEL_MARGIN)
return (x, y)
def make_layer_matrix(z):
layer_matrix = [[None for y in range(math.ceil(RAD_Y))] for x in range(math.ceil(RAD_X))]
# Generate the upper left corner.
furthest_x = RAD_X
furthest_y = RAD_Y
for y in range(math.ceil(RAD_Y)):
for x in range(math.ceil(RAD_X)):
ux = x + 0.5
uy = y + 0.5
uz = z + 0.5
within = in_ellipsoid(ux, uy, uz, RAD_X, RAD_Y, RAD_Z)
if WALL_THICKNESS:
in_hole = in_ellipsoid(
ux, uy, uz,
INNER_RAD_X, INNER_RAD_Y, INNER_RAD_Z,
RAD_X, RAD_Y, RAD_Z
)
within = within and not in_hole
if within:
if x in X_CENTER or y in Y_CENTER:
if z in Z_CENTER:
dot = dot_normal
else:
dot = dot_highlight
else:
if z in Z_CENTER:
dot = dot_highlight
else:
dot = dot_normal
layer_matrix[x][y] = dot
furthest_x = min(x, furthest_x)
furthest_y = min(y, furthest_y)
#layer_image.paste(dot, box=(pixel_coord_x, pixel_coord_y))
# Mark the corner pieces
for y in range(furthest_y, math.ceil(RAD_Y-1)):
for x in range(furthest_x, math.ceil(RAD_X-1)):
is_corner = (
layer_matrix[x][y] is not None and
layer_matrix[x-1][y+1] is not None and
layer_matrix[x+1][y-1] is not None and
(
# Outer corners
(layer_matrix[x][y-1] is None and layer_matrix[x-1][y] is None) or
# Inner corners, if hollow
(layer_matrix[x][y+1] is None and layer_matrix[x+1][y] is None)
)
)
if is_corner:
layer_matrix[x][y] = dot_corner
return layer_matrix
def make_layer_image(layer_matrix):
layer_image = PIL.Image.new('RGBA', size=(IMAGE_WIDTH, IMAGE_HEIGH), color=(0, 0, 0, 0))
draw = PIL.ImageDraw.ImageDraw(layer_image)
# Plot.
for y in range(math.ceil(RAD_Y)):
for x in range(math.ceil(RAD_X)):
right_x = (WIDTH - 1) - x
bottom_y = (HEIGH - 1) - y
if layer_matrix[x][y] is not None:
layer_image.paste(layer_matrix[x][y], box=pixel_coord(x, y))
layer_image.paste(layer_matrix[x][y], box=pixel_coord(right_x, y))
layer_image.paste(layer_matrix[x][y], box=pixel_coord(x, bottom_y))
layer_image.paste(layer_matrix[x][y], box=pixel_coord(right_x, bottom_y))
# To draw the guidelines, start from
for x in range(GUIDELINE_MOD_X % 4, WIDTH + 4, 4):
# Vertical guideline
as_if = GUIDELINE_MOD_X - x
#print(x, as_if)
line_x = PIXELSPACE_START_X + (x * pixel_scale) + (x * PIXEL_MARGIN)
line_x = line_x - PIXEL_MARGIN + (PIXEL_MARGIN // 2)
if line_x >= PIXELSPACE_END_X:
continue
(color, width) = choose_guideline_style(as_if)
draw.line((line_x, CANVAS_START_Y, line_x, CANVAS_END_Y - 1), fill=color, width=width)
draw.text((line_x, CANVAS_END_X), str(x), fill='#000')
for y in range(GUIDELINE_MOD_Y % 4, HEIGH + 4, 4):
# Horizontal guideline
as_if = GUIDELINE_MOD_Y - y
#print(y, as_if)
line_y = PIXELSPACE_START_Y + (y * pixel_scale) + (y * PIXEL_MARGIN)
line_y = line_y - PIXEL_MARGIN + (PIXEL_MARGIN // 2)
if line_y >= PIXELSPACE_END_Y:
continue
(color, width) = choose_guideline_style(as_if)
draw.line((CANVAS_START_X, line_y, CANVAS_END_X - 1, line_y), fill=color, width=width)
draw.text((CANVAS_END_X, line_y), str(y), fill='#000')
draw.rectangle((CANVAS_START_X, CANVAS_START_Y, CANVAS_END_X - 1, CANVAS_END_Y - 1), outline='#000')
draw.text((CANVAS_START_X, IMAGE_HEIGH - LABEL_HEIGH), layer_filename, fill='#000')
print(layer_filename)
if FINAL_IMAGE_SCALE != 1:
layer_image = layer_image.resize((FINAL_IMAGE_SCALE * IMAGE_WIDTH, FINAL_IMAGE_SCALE * IMAGE_HEIGH))
return layer_image
layer_matrices = []
for z in range(DEPTH):
if z < math.ceil(RAD_Z):
layer_matrix = make_layer_matrix(z)
layer_matrices.append(layer_matrix)
else:
layer_matrix = layer_matrices[(DEPTH - 1) - z]
layer_filename = filename_form.format(layer=z)
layer_image = make_layer_image(layer_matrix)
layer_image.save(layer_filename)
# Copy to the upper right corner.
#for y in range(math.ceil(RAD_Y)):
# #print(y)
# for x in range(math.ceil(RAD_X), WIDTH):
# #print(x, '==', (WIDTH-1) - x)
# mapped_x = (WIDTH - 1) - x
# layer_matrix[x][y] = layer_matrix[mapped_x][y]
# Copy to the lower semicircle.
#for y in range(math.ceil(RAD_Y), HEIGH):
# #print(y)
# for x in range(WIDTH):
# #print(y, '==', (HEIGH-1) - y)
# mapped_y = (HEIGH-1) - y
# layer_matrix[x][y] = layer_matrix[x][mapped_y]
#break
#layer_matrix = [['▓' if dot == dot_highlight else '░' if dot == dot_normal else ' 'for dot in sublist] for sublist in layer_matrix]
#layer_matrix = [''.join(sublist) for sublist in layer_matrix]
#layer_matrix = '\n'.join(layer_matrix)
#print(layer_matrix)
#print()
def voxelsphere_argparse(args):
height_depth_match = bool(args.height) == bool(args.depth)
if not height_depth_match:
raise ValueError('Must provide both or neither of height+depth. Not just one.')
if (args.height is args.depth is None):
args.height = args.width
args.depth = args.width
voxelspheregenerator(
int(args.width),
int(args.height),
int(args.depth),
WALL_THICKNESS=int(args.wall_thickness) if args.wall_thickness else None,
)
def main(argv):
parser = argparse.ArgumentParser()
parser.add_argument('width')
parser.add_argument('height', nargs='?', default=None)
parser.add_argument('depth', nargs='?', default=None)
parser.add_argument('--wall', dest='wall_thickness', default=None)
parser.set_defaults(func=voxelsphere_argparse)
args = parser.parse_args(argv)
args.func(args)
if __name__ == '__main__':
main(sys.argv[1:])

3
WebstreamZip/README.md Normal file
View File

@ -0,0 +1,3 @@
PLEASE DON'T USE THIS
Use [python-zipstream](https://github.com/allanlei/python-zipstream) instead.

Binary file not shown.

View File

@ -1,7 +0,0 @@
import webstreamzip
g = webstreamzip.stream_zip({'C:\\git\\else\\readme.md':'michael.md'})
x = open('test.zip', 'wb')
for chunk in g:
x.write(chunk)

View File

@ -10,6 +10,7 @@ PATHS = [
'C:\\git\\else\\Pathclass\\pathclass.py',
'C:\\git\\else\\Ratelimiter\\ratelimiter.py',
'C:\\git\\else\\RateMeter\\ratemeter.py',
'C:\\git\\else\\Safeprint\\safeprint.py',
'C:\\git\\else\\SpinalTap\\spinal.py',
'C:\\git\\else\\WebstreamZip\\webstreamzip.py',
]
@ -40,7 +41,7 @@ import setuptools
setuptools.setup(
author='voussoir',
name='{package}',
version='0.0.3',
version='0.0.4',
description='',
py_modules=[{py_modules}],
)

Binary file not shown.