From 188ce87d07f6fd18cfe2db2713d86f30de052ded Mon Sep 17 00:00:00 2001 From: Lorenzo Gil Sanchez Date: Fri, 29 Apr 2016 20:57:26 -0700 Subject: [PATCH 1/2] Support Python 3 without the 2to3 tool --- glue/algorithms/__init__.py | 12 ++++++------ glue/bin.py | 21 +++++++++++---------- glue/compat.py | 29 +++++++++++++++++++++++++++++ glue/core.py | 32 ++++++++++++++++++-------------- glue/formats/base.py | 3 ++- glue/formats/caat.py | 2 +- glue/formats/cocos2d.py | 2 +- glue/formats/css.py | 17 +++++++++-------- glue/formats/img.py | 9 +++++---- glue/formats/jsonformat.py | 8 ++++---- glue/formats/less.py | 2 +- glue/formats/scss.py | 2 +- glue/helpers.py | 6 ++++-- glue/managers/base.py | 4 ++-- glue/managers/watch.py | 2 +- setup.py | 1 - 16 files changed, 95 insertions(+), 57 deletions(-) create mode 100644 glue/compat.py diff --git a/glue/algorithms/__init__.py b/glue/algorithms/__init__.py index c9413bf..8b0979c 100644 --- a/glue/algorithms/__init__.py +++ b/glue/algorithms/__init__.py @@ -1,9 +1,9 @@ -from diagonal import DiagonalAlgorithm -from horizontal import HorizontalAlgorithm -from horizontal_bottom import HorizontalBottomAlgorithm -from square import SquareAlgorithm -from vertical import VerticalAlgorithm -from vertical_right import VerticalRightAlgorithm +from .diagonal import DiagonalAlgorithm +from .horizontal import HorizontalAlgorithm +from .horizontal_bottom import HorizontalBottomAlgorithm +from .square import SquareAlgorithm +from .vertical import VerticalAlgorithm +from .vertical_right import VerticalRightAlgorithm algorithms = {'diagonal': DiagonalAlgorithm, 'horizontal': HorizontalAlgorithm, diff --git a/glue/bin.py b/glue/bin.py index fe2c4c8..259e7d5 100755 --- a/glue/bin.py +++ b/glue/bin.py @@ -5,6 +5,7 @@ from PIL import Image as PImage +from glue.compat import itervalues, iterkeys, text_type from glue.formats import formats from glue.helpers import redirect_stdout from glue import exceptions @@ -20,13 +21,13 @@ def main(argv=None): parser.add_argument("--source", "-s", dest="source", - type=unicode, + type=text_type, default=os.environ.get('GLUE_SOURCE', None), help="Source path") parser.add_argument("--output", "-o", dest="output", - type=unicode, + type=text_type, default=os.environ.get('GLUE_OUTPUT', None), help="Output path") @@ -80,7 +81,7 @@ def main(argv=None): group.add_argument("-a", "--algorithm", dest="algorithm", metavar='NAME', - type=unicode, + type=text_type, default=os.environ.get('GLUE_ALGORITHM', 'square'), choices=['square', 'vertical', 'horizontal', 'vertical-right', 'horizontal-bottom', @@ -92,7 +93,7 @@ def main(argv=None): group.add_argument("--ordering", dest="algorithm_ordering", metavar='NAME', - type=unicode, + type=text_type, default=os.environ.get('GLUE_ORDERING', 'maxside'), choices=['maxside', 'width', 'height', 'area', 'filename', '-maxside', '-width', '-height', '-area', '-filename'], @@ -100,7 +101,7 @@ def main(argv=None): "filename (default: maxside)")) # Populate the parser with options required by other formats - for format in formats.itervalues(): + for format in itervalues(formats): format.populate_argument_parser(parser) # @@ -146,7 +147,7 @@ def add_deprecated_argument(*args, **kwargs): options.enabled_formats.remove('img') # Fail if any of the deprecated arguments is used - for argument in deprecated_arguments.iterkeys(): + for argument in iterkeys(deprecated_arguments): if getattr(options, argument, None): parser.error(("{0} argument is deprectated " "since v0.3").format(deprecated_arguments[argument])) @@ -233,16 +234,16 @@ def add_deprecated_argument(*args, **kwargs): manager.process() else: manager.process() - except exceptions.ValidationError, e: + except exceptions.ValidationError as e: sys.stderr.write(e.args[0]) return e.error_code - except exceptions.SourceImagesNotFoundError, e: + except exceptions.SourceImagesNotFoundError as e: sys.stderr.write("Error: No images found in %s.\n" % e.args[0]) return e.error_code - except exceptions.NoSpritesFoldersFoundError, e: + except exceptions.NoSpritesFoldersFoundError as e: sys.stderr.write("Error: No sprites folders found in %s.\n" % e.args[0]) return e.error_code - except exceptions.PILUnavailableError, e: + except exceptions.PILUnavailableError as e: sys.stderr.write(("Error: PIL {0} decoder is unavailable" "Please read the documentation and " "install it before spriting this kind of " diff --git a/glue/compat.py b/glue/compat.py new file mode 100644 index 0000000..3718169 --- /dev/null +++ b/glue/compat.py @@ -0,0 +1,29 @@ +import sys + +PY3 = sys.version_info[0] == 3 + +if PY3: # pragma: no cover + text_type = str + binary_type = bytes + + def itervalues(d): + return d.values() + + def iterkeys(d): + return d.keys() + + def iteritems(d): + return d.items() + +else: # pragma: no cover + text_type = unicode + binary_type = str + + def itervalues(d): + return d.itervalues() + + def iterkeys(d): + return d.iterkeys() + + def iteritems(d): + return d.iteritems() diff --git a/glue/core.py b/glue/core.py index 52b9315..c44c49e 100644 --- a/glue/core.py +++ b/glue/core.py @@ -3,12 +3,20 @@ import sys import copy import hashlib -import StringIO -import ConfigParser +try: + from StringIO import StringIO +except ImportError: + from io import BytesIO as StringIO + +try: + from ConfigParser import RawConfigParser, NoSectionError +except ImportError: + from configparser import RawConfigParser, NoSectionError from PIL import Image as PILImage from glue.algorithms import algorithms +from glue.compat import iteritems from glue.helpers import cached_property, round_up from glue.formats import ImageFormat from glue.exceptions import SourceImagesNotFoundError, PILUnavailableError @@ -23,11 +31,11 @@ def _get_config_from_file(self, filename, section): def clean(value): return {'true': True, 'false': False}.get(value.lower(), value) - config = ConfigParser.RawConfigParser() + config = RawConfigParser() config.read(os.path.join(self.config_path, filename)) try: keys = config.options(section) - except ConfigParser.NoSectionError: + except NoSectionError: return {} return dict([[k, clean(config.get(section, k))] for k in keys]) @@ -48,16 +56,13 @@ def __init__(self, path, config): with open(self.path, "rb") as img: self._image_data = img.read() - print "\t{0} added to sprite".format(self.filename) + print("\t{0} added to sprite".format(self.filename)) @cached_property def image(self): """Return a Pil representation of this image """ - if sys.version < '3': - imageio = StringIO.StringIO(self._image_data) - else: - imageio = StringIO.BytesIO(self._image_data) + imageio = StringIO(self._image_data) try: source_image = PILImage.open(imageio) @@ -70,7 +75,7 @@ def image(self): img.paste(source_image, (0, 0), mask=mask) else: img.paste(source_image, (0, 0)) - except IOError, e: + except IOError as e: raise PILUnavailableError(e.args[0].split()[1]) finally: imageio.close() @@ -105,7 +110,6 @@ def margin(self): return self._generate_spacing_info(self.config['margin']) def _generate_spacing_info(self, data): - data = data.split(',' if ',' in data else ' ') if len(data) == 4: @@ -119,7 +123,7 @@ def _generate_spacing_info(self, data): else: data = [0] * 4 - return map(int, data) + return list(map(int, data)) @cached_property def horizontal_spacing(self): @@ -196,7 +200,7 @@ def __init__(self, path, config, name=None): if ratio_output_key not in self.config: self.config[ratio_output_key] = img_format.output_path(ratio) - print "Processing '{0}':".format(self.name) + print("Processing '{0}':".format(self.name)) # Generate sprite map self.process() @@ -220,7 +224,7 @@ def hash(self): hash_list.append(os.path.relpath(image.path)) hash_list.append(image._image_data) - for key, value in self.config.iteritems(): + for key, value in iteritems(self.config): hash_list.append(key) hash_list.append(value) diff --git a/glue/formats/base.py b/glue/formats/base.py index e0abb4b..7724d04 100644 --- a/glue/formats/base.py +++ b/glue/formats/base.py @@ -9,6 +9,7 @@ from glue.helpers import round_up, nearest_fration from glue import __version__ +from glue.compat import iteritems class BaseFormat(object): @@ -54,7 +55,7 @@ def validate(self): @property def format_label(self): from glue.formats import formats - return dict((v,k) for k, v in formats.iteritems())[self.__class__] + return dict((v, k) for k, v in iteritems(formats))[self.__class__] @classmethod def populate_argument_parser(cls, parser): diff --git a/glue/formats/caat.py b/glue/formats/caat.py index 79c722b..5705132 100644 --- a/glue/formats/caat.py +++ b/glue/formats/caat.py @@ -1,6 +1,6 @@ import os -from base import BaseJSONFormat +from .base import BaseJSONFormat class CAATFormat(BaseJSONFormat): diff --git a/glue/formats/cocos2d.py b/glue/formats/cocos2d.py index ccbeaf6..6640618 100644 --- a/glue/formats/cocos2d.py +++ b/glue/formats/cocos2d.py @@ -1,6 +1,6 @@ import os -from base import BasePlistFormat +from .base import BasePlistFormat class Cocos2dFormat(BasePlistFormat): diff --git a/glue/formats/css.py b/glue/formats/css.py index ecb7177..7ce1898 100644 --- a/glue/formats/css.py +++ b/glue/formats/css.py @@ -3,7 +3,8 @@ import codecs from glue import __version__ -from base import JinjaTextFormat +from glue.compat import iteritems, text_type +from .base import JinjaTextFormat from ..exceptions import ValidationError @@ -54,20 +55,20 @@ def populate_argument_parser(cls, parser): group.add_argument("--namespace", dest="css_namespace", - type=unicode, + type=text_type, default=os.environ.get('GLUE_CSS_NAMESPACE', 'sprite'), help="Namespace for all css classes (default: sprite)") group.add_argument("--sprite-namespace", dest="css_sprite_namespace", - type=unicode, + type=text_type, default=os.environ.get('GLUE_CSS_SPRITE_NAMESPACE', '{sprite_name}'), help="Namespace for all sprites (default: {sprite_name})") group.add_argument("-u", "--url", dest="css_url", - type=unicode, + type=text_type, default=os.environ.get('GLUE_CSS_URL', ''), help="Prepend this string to the sprites path") @@ -94,7 +95,7 @@ def populate_argument_parser(cls, parser): group.add_argument("--separator", dest="css_separator", - type=unicode, + type=text_type, default=os.environ.get('GLUE_CSS_SEPARATOR', '-'), metavar='SEPARATOR', help=("Customize the separator used to join CSS class " @@ -103,7 +104,7 @@ def populate_argument_parser(cls, parser): group.add_argument("--pseudo-class-separator", dest="css_pseudo_class_separator", - type=unicode, + type=text_type, default=os.environ.get('GLUE_CSS_PSEUDO_CLASS_SEPARATOR', '__'), metavar='SEPARATOR', help=("Customize the separator glue will use in order " @@ -163,7 +164,7 @@ def get_context(self, *args, **kwargs): if self.sprite.config['css_url']: context['sprite_path'] = '{0}{1}'.format(self.sprite.config['css_url'], context['sprite_filename']) - for r, ratio in context['ratios'].iteritems(): + for r, ratio in iteritems(context['ratios']): ratio['sprite_path'] = '{0}{1}'.format(self.sprite.config['css_url'], ratio['sprite_filename']) # Add cachebuster if required @@ -174,7 +175,7 @@ def apply_cachebuster(path): context['sprite_path'] = apply_cachebuster(context['sprite_path']) - for r, ratio in context['ratios'].iteritems(): + for r, ratio in iteritems(context['ratios']): ratio['sprite_path'] = apply_cachebuster(ratio['sprite_path']) return context diff --git a/glue/formats/img.py b/glue/formats/img.py index eb72ecd..71a6417 100644 --- a/glue/formats/img.py +++ b/glue/formats/img.py @@ -4,6 +4,7 @@ from PIL import PngImagePlugin from glue import __version__ +from glue.compat import text_type from glue.helpers import round_up, cached_property from .base import BaseFormat @@ -19,7 +20,7 @@ def populate_argument_parser(cls, parser): group.add_argument("--img", dest="img_dir", - type=unicode, + type=text_type, default=os.environ.get('GLUE_IMG', True), metavar='DIR', help="Output directory for img files") @@ -38,13 +39,13 @@ def populate_argument_parser(cls, parser): group.add_argument("-p", "--padding", dest="padding", - type=unicode, + type=text_type, default=os.environ.get('GLUE_PADDING', '0'), help="Force this padding in all images") group.add_argument("--margin", dest="margin", - type=unicode, + type=text_type, default=os.environ.get('GLUE_MARGIN', '0'), help="Force this margin in all images") @@ -57,7 +58,7 @@ def populate_argument_parser(cls, parser): group.add_argument("--ratios", dest="ratios", - type=unicode, + type=text_type, default=os.environ.get('GLUE_RATIOS', '1'), help="Create sprites based on these ratios") diff --git a/glue/formats/jsonformat.py b/glue/formats/jsonformat.py index ea32a08..f7bdde6 100644 --- a/glue/formats/jsonformat.py +++ b/glue/formats/jsonformat.py @@ -1,12 +1,12 @@ import os -import json try: from collections import OrderedDict except ImportError: from ordereddict import OrderedDict -from base import BaseJSONFormat +from glue.compat import text_type +from .base import BaseJSONFormat class JSONFormat(BaseJSONFormat): @@ -29,7 +29,7 @@ def populate_argument_parser(cls, parser): group.add_argument("--json-format", dest="json_format", metavar='NAME', - type=unicode, + type=text_type, default=os.environ.get('GLUE_JSON_FORMAT', 'array'), choices=['array', 'hash'], help=("JSON structure format (array, hash)")) @@ -60,7 +60,7 @@ def get_context(self, *args, **kwargs): 'height': context['height']}) if self.sprite.config['json_format'] == 'array': - data['frames'] = frames.values() + data['frames'] = list(frames.values()) else: data['frames'] = frames diff --git a/glue/formats/less.py b/glue/formats/less.py index dd07638..c557dca 100644 --- a/glue/formats/less.py +++ b/glue/formats/less.py @@ -1,6 +1,6 @@ import os -from css import CssFormat +from .css import CssFormat class LessFormat(CssFormat): diff --git a/glue/formats/scss.py b/glue/formats/scss.py index c9bf49e..6e1c659 100644 --- a/glue/formats/scss.py +++ b/glue/formats/scss.py @@ -1,6 +1,6 @@ import os -from css import CssFormat +from .css import CssFormat class ScssFormat(CssFormat): diff --git a/glue/helpers.py b/glue/helpers.py index 4d51c3b..5556d67 100644 --- a/glue/helpers.py +++ b/glue/helpers.py @@ -1,7 +1,9 @@ -import os import sys import contextlib -from StringIO import StringIO +try: + from StringIO import StringIO +except ImportError: + from io import StringIO def round_up(value): diff --git a/glue/managers/base.py b/glue/managers/base.py index 6c658d3..6ae1edc 100644 --- a/glue/managers/base.py +++ b/glue/managers/base.py @@ -41,7 +41,7 @@ def save(self): format = format_cls(sprite=sprite) format.validate() if format.needs_rebuild() or sprite.config['force']: - print "Format '{0}' for sprite '{1}' needs rebuild...".format(format_name, sprite.name) + print("Format '{0}' for sprite '{1}' needs rebuild...".format(format_name, sprite.name)) format.build() else: - print "Format '{0}'' for sprite '{1}' already exists...".format(format_name, sprite.name) + print("Format '{0}'' for sprite '{1}' already exists...".format(format_name, sprite.name)) diff --git a/glue/managers/watch.py b/glue/managers/watch.py index 51875eb..18e0e6a 100644 --- a/glue/managers/watch.py +++ b/glue/managers/watch.py @@ -39,5 +39,5 @@ def generate_hash(self): def signal_handler(self, signal, frame): """ Gracefully close the app if Ctrl+C is pressed.""" - print 'You pressed Ctrl+C!' + print('You pressed Ctrl+C!') sys.exit(0) diff --git a/setup.py b/setup.py index 6d33ec9..405a6a3 100644 --- a/setup.py +++ b/setup.py @@ -57,5 +57,4 @@ ] }, zip_safe = False, - use_2to3=True ) From f89a0c1f7bbd3b95d83435050728a295ad51a44a Mon Sep 17 00:00:00 2001 From: Lorenzo Gil Sanchez Date: Mon, 6 Sep 2021 21:53:35 -0700 Subject: [PATCH 2/2] Support Python3 in the Sphinx conf file too --- docs/conf.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index d58bfff..0236aa9 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -53,10 +53,10 @@ try: release = pkg_resources.get_distribution('glue').version except pkg_resources.DistributionNotFound: - print 'To build the documentation, The distribution information of glue' - print 'Has to be available. Either install the package into your' - print 'development environment or run "setup.py develop" to setup the' - print 'metadata. A virtualenv is recommended!' + print('To build the documentation, The distribution information of glue') + print('Has to be available. Either install the package into your') + print('development environment or run "setup.py develop" to setup the') + print('metadata. A virtualenv is recommended!') sys.exit(1) del pkg_resources