Merge pull request #79 from dylanaraps/35

general: Add support for Python 3.5
This commit is contained in:
Dylan Araps 2017-08-12 18:42:27 +10:00 committed by GitHub
commit 8be48c07ff
15 changed files with 102 additions and 96 deletions

View File

@ -1,5 +1,6 @@
language: python language: python
python: python:
- "3.5"
- "3.6" - "3.6"
before_install: before_install:

View File

@ -87,14 +87,15 @@ def process_args(args):
sys.exit(1) sys.exit(1)
if args.v: if args.v:
print(f"wal {__version__}") print("wal", __version__)
sys.exit(0) sys.exit(0)
if args.q: if args.q:
sys.stdout = sys.stderr = open(os.devnull, "w") sys.stdout = sys.stderr = open(os.devnull, "w")
if args.c: if args.c:
shutil.rmtree(CACHE_DIR / "schemes", ignore_errors=True) scheme_dir = os.path.join(CACHE_DIR, "schemes")
shutil.rmtree(scheme_dir, ignore_errors=True)
if args.r: if args.r:
reload.colors(args.t) reload.colors(args.t)

View File

@ -1,6 +1,7 @@
""" """
Generate a colorscheme using imagemagick. Generate a colorscheme using imagemagick.
""" """
import os
import re import re
import shutil import shutil
import subprocess import subprocess
@ -64,19 +65,17 @@ def sort_colors(img, colors):
# Create a comment color from the background. # Create a comment color from the background.
raw_colors[8] = util.lighten_color(raw_colors[0], 0.40) raw_colors[8] = util.lighten_color(raw_colors[0], 0.40)
colors = {"wallpaper": img} colors = {}
colors_special = {} colors["wallpaper"] = img
colors_hex = {} colors["special"] = {}
colors["colors"] = {}
colors_special.update({"background": raw_colors[0]}) colors["special"]["background"] = raw_colors[0]
colors_special.update({"foreground": raw_colors[15]}) colors["special"]["foreground"] = raw_colors[15]
colors_special.update({"cursor": raw_colors[15]}) colors["special"]["cursor"] = raw_colors[15]
for index, color in enumerate(raw_colors): for index, color in enumerate(raw_colors):
colors_hex.update({f"color{index}": color}) colors["colors"]["color%s" % index] = color
colors["special"] = colors_special
colors["colors"] = colors_hex
return colors return colors
@ -85,11 +84,10 @@ def get(img, cache_dir=CACHE_DIR,
color_count=COLOR_COUNT, notify=False): color_count=COLOR_COUNT, notify=False):
"""Get the colorscheme.""" """Get the colorscheme."""
# _home_dylan_img_jpg.json # _home_dylan_img_jpg.json
cache_file = cache_dir / "schemes" / \ cache_file = img.replace("/", "_").replace(".", "_")
img.replace("/", "_").replace(".", "_") cache_file = os.path.join(cache_dir, "schemes", cache_file + ".json")
cache_file = cache_file.with_suffix(".json")
if cache_file.is_file(): if os.path.isfile(cache_file):
colors = util.read_file_json(cache_file) colors = util.read_file_json(cache_file)
print("colors: Found cached colorscheme.") print("colors: Found cached colorscheme.")

View File

@ -2,7 +2,6 @@
Export colors in various formats. Export colors in various formats.
""" """
import os import os
import pathlib
from .settings import CACHE_DIR, MODULE_DIR from .settings import CACHE_DIR, MODULE_DIR
from . import util from . import util
@ -43,10 +42,10 @@ def get_export_type(export_type):
def every(colors, output_dir=CACHE_DIR): def every(colors, output_dir=CACHE_DIR):
"""Export all template files.""" """Export all template files."""
all_colors = flatten_colors(colors) all_colors = flatten_colors(colors)
output_dir = pathlib.Path(output_dir) template_dir = os.path.join(MODULE_DIR, "templates")
for file in os.scandir(MODULE_DIR / "templates"): for file in os.scandir(template_dir):
template(all_colors, file.path, output_dir / file.name) template(all_colors, file.path, os.path.join(output_dir, file.name))
print("export: Exported all files.") print("export: Exported all files.")
@ -56,11 +55,11 @@ def color(colors, export_type, output_file=None):
all_colors = flatten_colors(colors) all_colors = flatten_colors(colors)
template_name = get_export_type(export_type) template_name = get_export_type(export_type)
template_file = MODULE_DIR / "templates" / template_name template_file = os.path.join(MODULE_DIR, "templates", template_name)
output_file = output_file or CACHE_DIR / template_name output_file = output_file or os.path.join(CACHE_DIR, template_name)
if template_file.is_file(): if os.path.isfile(template_file):
template(all_colors, template_file, output_file) template(all_colors, template_file, output_file)
print(f"export: Exported {export_type}.") print("export: Exported %s." % export_type)
else: else:
print(f"[!] warning: template '{export_type}' doesn't exist.") print("warning: template '%s' doesn't exist." % export_type)

View File

@ -2,7 +2,6 @@
Get the image file. Get the image file.
""" """
import os import os
import pathlib
import random import random
import sys import sys
@ -24,25 +23,23 @@ def get_random_image(img_dir):
print("image: No new images found (nothing to do), exiting...") print("image: No new images found (nothing to do), exiting...")
sys.exit(1) sys.exit(1)
return str(img_dir / random.choice(images).name) return os.path.join(img_dir, random.choice(images).name)
def get(img, cache_dir=CACHE_DIR): def get(img, cache_dir=CACHE_DIR):
"""Validate image input.""" """Validate image input."""
image = pathlib.Path(img) if os.path.isfile(img):
wal_img = img
if image.is_file(): elif os.path.isdir(img):
wal_img = str(image) wal_img = get_random_image(img)
elif image.is_dir():
wal_img = get_random_image(image)
else: else:
print("error: No valid image file found.") print("error: No valid image file found.")
sys.exit(1) sys.exit(1)
# Cache the image file path. # Cache the image file path.
util.save_file(wal_img, cache_dir / "wal") util.save_file(wal_img, os.path.join(cache_dir, "wal"))
print("image: Using image", wal_img) print("image: Using image", wal_img)
return wal_img return wal_img

View File

@ -1,6 +1,7 @@
""" """
Reload programs. Reload programs.
""" """
import os
import re import re
import shutil import shutil
import subprocess import subprocess
@ -12,7 +13,7 @@ from . import util
def xrdb(xrdb_file=None): def xrdb(xrdb_file=None):
"""Merge the colors into the X db so new terminals use them.""" """Merge the colors into the X db so new terminals use them."""
xrdb_file = xrdb_file or CACHE_DIR / "colors.Xresources" xrdb_file = xrdb_file or os.path.join(CACHE_DIR, "colors.Xresources")
if shutil.which("xrdb"): if shutil.which("xrdb"):
subprocess.Popen(["xrdb", "-merge", xrdb_file], subprocess.Popen(["xrdb", "-merge", xrdb_file],
@ -22,18 +23,18 @@ def xrdb(xrdb_file=None):
def gtk(): def gtk():
"""Move gtkrc files to the correct location.""" """Move gtkrc files to the correct location."""
theme_path = HOME / ".themes" / "Flatabulous-wal" theme_path = os.path.join(HOME, ".themes", "Flatabulous-wal")
gtk2_file = CACHE_DIR / "colors-gtk2.rc" gtk2_file = os.path.join(CACHE_DIR, "colors-gtk2.rc")
if theme_path.is_dir(): if os.path.isdir(theme_path):
if gtk2_file.is_file(): shutil.copy(gtk2_file, os.path.join(theme_path, "gtk-2.0"))
shutil.copy(gtk2_file, theme_path / "gtk-2.0")
# Here we call a Python 2 script to reload the GTK themes. # Here we call a Python 2 script to reload the GTK themes.
# This is done because the Python 3 GTK/Gdk libraries don't # This is done because the Python 3 GTK/Gdk libraries don't
# provide a way of doing this. # provide a way of doing this.
if shutil.which("python2"): if shutil.which("python2"):
util.disown(["python2", MODULE_DIR / "scripts" / "gtk_reload.py"]) gtk_reload = os.path.join(MODULE_DIR, "scripts", "gtk_reload.py")
util.disown(["python2", gtk_reload])
else: else:
print("warning: GTK2 reload support requires Python 2.") print("warning: GTK2 reload support requires Python 2.")
@ -62,9 +63,9 @@ def env(xrdb_file=None):
def colors(vte, cache_dir=CACHE_DIR): def colors(vte, cache_dir=CACHE_DIR):
"""Reload the current scheme.""" """Reload the current scheme."""
sequence_file = cache_dir / "sequences" sequence_file = os.path.join(cache_dir, "sequences")
if sequence_file.is_file(): if os.path.isfile(sequence_file):
sequences = "".join(util.read_file(sequence_file)) sequences = "".join(util.read_file(sequence_file))
# If vte mode was used, remove the unsupported sequence. # If vte mode was used, remove the unsupported sequence.

View File

@ -2,6 +2,7 @@
Send sequences to all open terminals. Send sequences to all open terminals.
""" """
import glob import glob
import os
from .settings import CACHE_DIR, OS from .settings import CACHE_DIR, OS
from . import util from . import util
@ -12,37 +13,37 @@ def set_special(index, color, iterm_name="h"):
alpha = util.Color.alpha_num alpha = util.Color.alpha_num
if OS == "Darwin": if OS == "Darwin":
return f"\033]P{iterm_name}{color.strip('#')}\033\\" return "\033[P%s%s\033\\" % (iterm_name, color.strip("#"))
if index in [11, 708] and alpha != 100: if index in [11, 708] and alpha != 100:
return f"\033]{index};[{alpha}]{color}\007" return "\033]%s;[%s]%s\007" % (index, alpha, color)
return f"\033]{index};{color}\007" return "\033]%s;%s\007" % (index, color)
def set_color(index, color): def set_color(index, color):
"""Convert a hex color to a text color sequence.""" """Convert a hex color to a text color sequence."""
if OS == "Darwin": if OS == "Darwin":
return f"\033]P{index:x}{color.strip('#')}\033\\" return "\033]P%x%s\033\\" % (index, color.strip("#"))
return f"\033]4;{index};{color}\007" return "\033]4;%s;%s\007" % (index, color)
def set_iterm_tab_color(color): def set_iterm_tab_color(color):
"""Set iTerm2 tab/window color""" """Set iTerm2 tab/window color"""
red, green, blue = util.hex_to_rgb(color) red, green, blue = util.hex_to_rgb(color)
return [ return """
f"\033]6;1;bg;red;brightness;{red}\a", \033]6;1;bg;red;brightness;%s\a
f"\033]6;1;bg;green;brightness;{green}\a", \033]6;1;bg;green;brightness;%s\a
f"\033]6;1;bg;blue;brightness;{blue}\a", \033]6;1;bg;blue;brightness;%s\a
] """ % (red, green, blue)
def create_sequences(colors, vte): def create_sequences(colors, vte):
"""Create the escape sequences.""" """Create the escape sequences."""
# Colors 0-15. # Colors 0-15.
sequences = [set_color(num, col) for num, col in sequences = [set_color(index, colors["colors"]["color%s" % index])
enumerate(colors["colors"].values())] for index in range(16)]
# Set a blank color that isn't affected by bold highlighting. # Set a blank color that isn't affected by bold highlighting.
# Used in wal.vim's airline theme. # Used in wal.vim's airline theme.
@ -81,5 +82,5 @@ def send(colors, vte, cache_dir=CACHE_DIR):
for term in glob.glob(tty_pattern): for term in glob.glob(tty_pattern):
util.save_file(sequences, term) util.save_file(sequences, term)
util.save_file(sequences, cache_dir / "sequences") util.save_file(sequences, os.path.join(cache_dir, "sequences"))
print("colors: Set terminal colors.") print("colors: Set terminal colors.")

View File

@ -9,15 +9,15 @@
Created by Dylan Araps. Created by Dylan Araps.
""" """
import pathlib import os
import platform import platform
__version__ = "0.5.13" __version__ = "0.5.13"
HOME = pathlib.Path.home() HOME = os.environ["HOME"]
CACHE_DIR = HOME / ".cache/wal/" CACHE_DIR = os.path.join(HOME, ".cache/wal/")
MODULE_DIR = pathlib.Path(__file__).parent MODULE_DIR = os.path.dirname(__file__)
COLOR_COUNT = 16 COLOR_COUNT = 16
OS = platform.uname()[0] OS = platform.uname()[0]

View File

@ -3,7 +3,6 @@ Misc helper functions.
""" """
import json import json
import os import os
import pathlib
import subprocess import subprocess
@ -21,7 +20,7 @@ class Color:
def rgb(self): def rgb(self):
"""Convert a hex color to rgb.""" """Convert a hex color to rgb."""
red, green, blue = hex_to_rgb(self.hex_color) red, green, blue = hex_to_rgb(self.hex_color)
return f"{red},{green},{blue}" return "%s,%s,%s" % (red, green, blue)
@property @property
def xrgba(self): def xrgba(self):
@ -31,7 +30,7 @@ class Color:
@property @property
def alpha(self): def alpha(self):
"""Add URxvt alpha value to color.""" """Add URxvt alpha value to color."""
return f"[{self.alpha_num}]{self.hex_color}" return "[%s]%s" % (self.alpha_num, self.hex_color)
def read_file(input_file): def read_file(input_file):
@ -65,7 +64,7 @@ def save_file(data, export_file):
with open(export_file, "w") as file: with open(export_file, "w") as file:
file.write(data) file.write(data)
except PermissionError: except PermissionError:
print(f"[!] warning: Couldn't write to {export_file}.") print("warning: Couldn't write to %s." % export_file)
def save_file_json(data, export_file): def save_file_json(data, export_file):
@ -78,7 +77,7 @@ def save_file_json(data, export_file):
def create_dir(directory): def create_dir(directory):
"""Alias to create the cache dir.""" """Alias to create the cache dir."""
pathlib.Path(directory).mkdir(parents=True, exist_ok=True) os.makedirs(directory, exist_ok=True)
def hex_to_rgb(color): def hex_to_rgb(color):
@ -88,13 +87,13 @@ def hex_to_rgb(color):
def hex_to_xrgba(color): def hex_to_xrgba(color):
"""Convert a hex color to xrdb rgba.""" """Convert a hex color to xrdb rgba."""
col = color.lower() col = color.lower().strip("#")
return f"{col[1]}{col[2]}/{col[3]}{col[4]}/{col[5]}{col[6]}/ff" return "%s%s/%s%s/%s%s/ff" % (*col,)
def rgb_to_hex(color): def rgb_to_hex(color):
"""Convert an rgb color to hex.""" """Convert an rgb color to hex."""
return f"#{color[0]:02x}{color[1]:02x}{color[2]:02x}" return "#%02x%02x%02x" % (*color,)
def darken_color(color, amount): def darken_color(color, amount):

View File

@ -84,7 +84,7 @@ def set_desktop_wallpaper(desktop, img):
def set_mac_wallpaper(img): def set_mac_wallpaper(img):
"""Set the wallpaper on macOS.""" """Set the wallpaper on macOS."""
db_file = HOME / "Library/Application Support/Dock/desktoppicture.db" db_file = HOME / "Library/Application Support/Dock/desktoppicture.db"
subprocess.call(["sqlite3", db_file, f"update data set value = '{img}'"]) subprocess.call(["sqlite3", db_file, "update data set value = '%s'" % img])
# Kill the dock to fix issues with cached wallpapers. # Kill the dock to fix issues with cached wallpapers.
# macOS caches wallpapers and if a wallpaper is set that shares # macOS caches wallpapers and if a wallpaper is set that shares
@ -114,9 +114,9 @@ def change(img):
def get(cache_dir=CACHE_DIR): def get(cache_dir=CACHE_DIR):
"""Get the current wallpaper.""" """Get the current wallpaper."""
current_wall = cache_dir / "wal" current_wall = os.path.join(cache_dir, "wal")
if current_wall.is_file(): if os.path.isfile(current_wall):
return util.read_file(current_wall)[0] return util.read_file(current_wall)[0]
return "None" return "None"

View File

@ -4,7 +4,7 @@ import setuptools
try: try:
import pywal import pywal
except (ImportError, SyntaxError): except (ImportError, SyntaxError):
print("error: pywal requires Python 3.6 or greater.") print("error: pywal requires Python 3.5 or greater.")
quit(1) quit(1)

View File

@ -2,7 +2,7 @@
import unittest import unittest
import unittest.mock import unittest.mock
import io import io
import pathlib import os
from pywal import export from pywal import export
from pywal import util from pywal import util
@ -11,7 +11,6 @@ from pywal import util
# Import colors. # Import colors.
COLORS = util.read_file_json("tests/test_files/test_file.json") COLORS = util.read_file_json("tests/test_files/test_file.json")
COLORS["colors"].update(COLORS["special"]) COLORS["colors"].update(COLORS["special"])
OUTPUT_DIR = pathlib.Path("/tmp/wal")
util.create_dir("/tmp/wal") util.create_dir("/tmp/wal")
@ -21,34 +20,36 @@ class TestExportColors(unittest.TestCase):
def test_all_templates(self): def test_all_templates(self):
"""> Test substitutions in template file.""" """> Test substitutions in template file."""
export.every(COLORS, OUTPUT_DIR) export.every(COLORS, "/tmp/wal")
result = pathlib.Path("/tmp/wal/colors.sh").is_file() result = os.path.isfile("/tmp/wal/colors.sh")
self.assertTrue(result) self.assertTrue(result)
content = pathlib.Path("/tmp/wal/colors.sh").read_text() with open("/tmp/wal/colors.sh") as file:
content = content.split("\n")[6] content = file.read().splitlines()
self.assertEqual(content, "foreground='#F5F1F4'")
self.assertEqual(content[6], "foreground='#F5F1F4'")
def test_css_template(self): def test_css_template(self):
"""> Test substitutions in template file (css).""" """> Test substitutions in template file (css)."""
export.color(COLORS, "css", OUTPUT_DIR / "test.css") export.color(COLORS, "css", "/tmp/wal/test.css")
result = pathlib.Path("/tmp/wal/test.css").is_file() result = os.path.isfile("/tmp/wal/test.css")
self.assertTrue(result) self.assertTrue(result)
content = pathlib.Path("/tmp/wal/test.css").read_text() with open("/tmp/wal/test.css") as file:
content = content.split("\n")[6] content = file.read().splitlines()
self.assertEqual(content, " --background: #1F211E;")
self.assertEqual(content[6], " --background: #1F211E;")
def test_invalid_template(self): def test_invalid_template(self):
"""> Test template validation.""" """> Test template validation."""
error_msg = "[!] warning: template 'dummy' doesn't exist." error_msg = "warning: template 'dummy' doesn't exist."
# Since this function prints a message on fail we redirect # Since this function prints a message on fail we redirect
# it's output so that we can read it. # it's output so that we can read it.
with unittest.mock.patch('sys.stdout', new=io.StringIO()) as fake_out: with unittest.mock.patch('sys.stdout', new=io.StringIO()) as fake_out:
export.color(COLORS, "dummy", OUTPUT_DIR / "test.css") export.color(COLORS, "dummy", "/tmp/wal/test.css")
self.assertEqual(fake_out.getvalue().strip(), error_msg) self.assertEqual(fake_out.getvalue().strip(), error_msg)

View File

@ -2,6 +2,8 @@
import unittest import unittest
import unittest.mock import unittest.mock
import os
from pywal import __main__ from pywal import __main__
from pywal import reload from pywal import reload
from pywal import wallpaper from pywal import wallpaper
@ -22,7 +24,8 @@ class TestMain(unittest.TestCase):
"""> Test arg parsing (-c).""" """> Test arg parsing (-c)."""
args = __main__.get_args(["-c"]) args = __main__.get_args(["-c"])
__main__.process_args(args) __main__.process_args(args)
self.assertFalse((CACHE_DIR / "schemes").is_dir()) scheme_dir = os.path.join(CACHE_DIR, "schemes")
self.assertFalse(os.path.isdir(scheme_dir))
def test_args_e(self): def test_args_e(self):
"""> Test arg parsing (-e).""" """> Test arg parsing (-e)."""

View File

@ -32,7 +32,14 @@ class Testsequences(unittest.TestCase):
def test_set_iterm_tab_color(self): def test_set_iterm_tab_color(self):
"""> Create iterm tab color sequences""" """> Create iterm tab color sequences"""
result = sequences.set_iterm_tab_color(COLORS["special"]["background"]) result = sequences.set_iterm_tab_color(COLORS["special"]["background"])
self.assertEqual(len(result), 3) self.assertEqual(len(result), 104)
def test_sequence_order(self):
"""> Test that the sequences are in order."""
result = sequences.create_sequences(COLORS, vte=False).split("\007")
self.assertEqual(result[2], "\x1b]4;2;#CC6A93")
self.assertEqual(result[15], "\x1b]4;15;#F5F1F4")
self.assertEqual(result[8], "\x1b]4;8;#666666")
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -1,7 +1,6 @@
"""Test util functions.""" """Test util functions."""
import unittest import unittest
import os import os
import pathlib
from pywal import util from pywal import util
@ -35,24 +34,23 @@ class TestUtil(unittest.TestCase):
def test_save_file(self): def test_save_file(self):
"""> Save colors to a file.""" """> Save colors to a file."""
tmp_file = pathlib.Path("/tmp/test_file") tmp_file = "/tmp/test_file"
util.save_file("Hello, world", tmp_file) util.save_file("Hello, world", tmp_file)
result = tmp_file.is_file() result = os.path.isfile(tmp_file)
self.assertTrue(result) self.assertTrue(result)
def test_save_file_json(self): def test_save_file_json(self):
"""> Save colors to a file.""" """> Save colors to a file."""
tmp_file = pathlib.Path("/tmp/test_file.json") tmp_file = "/tmp/test_file.json"
util.save_file_json(COLORS, tmp_file) util.save_file_json(COLORS, tmp_file)
result = tmp_file.is_file() result = os.path.isfile(tmp_file)
self.assertTrue(result) self.assertTrue(result)
def test_create_dir(self): def test_create_dir(self):
"""> Create a directory.""" """> Create a directory."""
tmp_dir = pathlib.Path("/tmp/test_dir") tmp_dir = "/tmp/test_dir"
util.create_dir(tmp_dir) util.create_dir(tmp_dir)
result = tmp_dir.is_dir() self.assertTrue(os.path.isdir(tmp_dir))
self.assertTrue(result)
os.rmdir(tmp_dir) os.rmdir(tmp_dir)
def test_hex_to_rgb_black(self): def test_hex_to_rgb_black(self):