diff --git a/.gitignore b/.gitignore index 1727b74..b546a05 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,9 @@ syntax: glob *.egg-info *.mo +*.swp *.pyc +*.py.bak .DS_Store .idea .installed.cfg diff --git a/CHANGES.rst b/CHANGES.rst index e76283b..6a66793 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -10,7 +10,9 @@ Breaking changes: New features: -- *add item here* +- Imports are Python3 compatible. Add six into install_requires set and sort + each file's imports with the isort package. + [b4oshany, @davilima6] Bug fixes: diff --git a/setup.py b/setup.py index bdd2e8f..a8dd1e9 100644 --- a/setup.py +++ b/setup.py @@ -1,5 +1,6 @@ -from setuptools import setup from setuptools import find_packages +from setuptools import setup + import sys version = '1.1.4.dev0' @@ -53,6 +54,7 @@ def indent(line): 'robotsuite', # not a direct dependency, but required for convenience 'selenium', 'setuptools', + 'six', 'zope.component', 'zope.configuration', 'zope.i18n', diff --git a/src/plone/app/robotframework/autologin.py b/src/plone/app/robotframework/autologin.py index fc226af..4a3e802 100644 --- a/src/plone/app/robotframework/autologin.py +++ b/src/plone/app/robotframework/autologin.py @@ -36,7 +36,7 @@ def set_autologin_username(self, username): raise Exception(u"Autologin is not enabled") if len(self.acl_users.robot_login._domain_map) == 0: raise Exception(u"Autologin is not enabled") - domain_map_key = self.acl_users.robot_login._domain_map.keys()[0] + domain_map_key = list(self.acl_users.robot_login._domain_map.keys())[0] domain_map = self.acl_users.robot_login._domain_map[domain_map_key] domain_map[0]['username'] = username self.acl_users.robot_login._domain_map[domain_map_key] = domain_map diff --git a/src/plone/app/robotframework/content.py b/src/plone/app/robotframework/content.py index 22b8811..9382216 100644 --- a/src/plone/app/robotframework/content.py +++ b/src/plone/app/robotframework/content.py @@ -1,8 +1,5 @@ # -*- coding: utf-8 -*- from datetime import datetime -import os - -from Products.CMFCore.utils import getToolByName from plone.app.robotframework.config import HAS_BLOBS from plone.app.robotframework.config import HAS_DEXTERITY from plone.app.robotframework.config import HAS_DEXTERITY_RELATIONS @@ -10,6 +7,7 @@ from plone.app.robotframework.utils import disableCSRFProtection from plone.i18n.normalizer.interfaces import IURLNormalizer from plone.uuid.interfaces import IUUID +from Products.CMFCore.utils import getToolByName from zope.component import ComponentLookupError from zope.component import getUtility from zope.component import queryUtility @@ -18,6 +16,10 @@ from zope.globalrequest import getRequest from zope.lifecycleevent import ObjectModifiedEvent +import os +import six + + if HAS_DEXTERITY: from plone.app.textfield.value import RichTextValue @@ -137,10 +139,10 @@ def create_content(self, *args, **kwargs): if widget and name in kwargs: if not IFromUnicode.providedBy(field): value = kwargs[name] - elif isinstance(kwargs[name], unicode): + elif isinstance(kwargs[name], six.text_type): value = kwargs[name] else: - value = unicode(str(kwargs[name]), 'utf-8', + value = six.text_type(str(kwargs[name]), 'utf-8', errors='ignore') converter = IDataConverter(widget) dm = queryMultiAdapter((content, field), IDataManager) @@ -283,7 +285,7 @@ def prefill_image_types(portal, kwargs): def random_image(): import random - import StringIO + from six import StringIO from PIL import Image from PIL import ImageDraw @@ -300,7 +302,7 @@ def random_image(): ) del draw - result = StringIO.StringIO() + result = StringIO() img.save(result, 'PNG') result.seek(0) return result diff --git a/src/plone/app/robotframework/pybabel.py b/src/plone/app/robotframework/pybabel.py index 9095d5c..73ead52 100644 --- a/src/plone/app/robotframework/pybabel.py +++ b/src/plone/app/robotframework/pybabel.py @@ -8,7 +8,7 @@ def populate(self): if self._value or self._comments: self._setter(self._value, self._comments.value) try: - parts = map(unicode.lower, self._value) + parts = map(six.text_type.lower, self._value) index = parts.index('translate') comments = [] for part in filter(lambda x: x.startswith('default='), self._value): @@ -19,10 +19,15 @@ def populate(self): except IndexError: pass +import robot import robot.parsing.tablepopulators +import six + + robot.parsing.tablepopulators.StepPopulator.populate = populate -import robot + + def extract_robot(fileobj, keywords, comment_tags, options): diff --git a/src/plone/app/robotframework/reload.py b/src/plone/app/robotframework/reload.py index 30b277b..418b653 100644 --- a/src/plone/app/robotframework/reload.py +++ b/src/plone/app/robotframework/reload.py @@ -37,7 +37,7 @@ def start(self): registerHandler(signal.SIGTERM, self._exitHandler) for path in self.paths: - print WAIT("Watchdog is watching for changes in %s" % path) + print(WAIT("Watchdog is watching for changes in %s" % path)) observer = Observer() self.observers.append(observer) observer.schedule(self, path=path, recursive=True) @@ -62,16 +62,16 @@ def on_any_event(self, event): break if self.last_event + self.minimum_wait < time.time(): - print WAIT("Watchdog got %s event on %s" - % (event_type, event_relpath)) + print(WAIT("Watchdog got %s event on %s" + % (event_type, event_relpath))) try: self.forkloop.forkNewChild() self.last_event = time.time() except Exception as e: - print ERROR(str(e)) + print(ERROR(str(e))) else: - print WAIT("Watchdog skipped %s event on %s" - % (event_type, event_relpath)) + print(WAIT("Watchdog skipped %s event on %s" + % (event_type, event_relpath))) class ForkLoop(object): @@ -132,7 +132,7 @@ def loop(self): self.active = True - print WAIT("Fork loop now starting on parent process %i" % os.getpid()) + print(WAIT("Fork loop now starting on parent process %i" % os.getpid())) while True: self.forking = False @@ -147,12 +147,12 @@ def loop(self): continue if not self.killed_child: - print ERROR( + print(ERROR( "Forked child process died on bootup. " "Fix possible errors and save edits. " "We are now paused until we detect the next file " "change..." - ) + )) # Child died because of unknown reason. Mark it as killed # and go into pause mode. @@ -175,7 +175,7 @@ def loop(self): self.forking = False - print WAIT("Fork loop forked a new child process %i" % (os.getpid())) + print(WAIT("Fork loop forked a new child process %i" % (os.getpid()))) def forkNewChild(self): """STEP 1 (parent): New child process forking starts by killing the @@ -201,7 +201,7 @@ def forkNewChild(self): else: # Ok, we already have sent the SIGINT the child, but asking for new # child - print WAIT("Fork loop scheduling a new fork") + print(WAIT("Fork loop scheduling a new fork")) self._scheduleFork() self.killed_child = True @@ -226,8 +226,8 @@ def _parentExitHandler(self, signum=None, frame=None): while self.isChildAlive(): # XXX: Somehow this may get stuck if we don't print before kill - print WAIT("Fork loop is terminating its child process %s" % - self.child_pid) + print(WAIT("Fork loop is terminating its child process %s" % + self.child_pid)) self._killChild() time.sleep(2) @@ -259,14 +259,14 @@ def _waitChildToDieAndScheduleNew(self, signal=None, frame=None): exit_flags.append("exited with code %d" % code) if exit_status == 0: - print WAIT("Fork loop terminated child process %d" % pid) + print(WAIT("Fork loop terminated child process %d" % pid)) elif exit_flags: - print ERROR("Forked child process %d %s" - % (pid, ", ".join(exit_flags))) + print(ERROR("Forked child process %d %s" + % (pid, ", ".join(exit_flags)))) else: - print ERROR("Forked child process %d exited with code %s" - % (pid, exit_status)) + print(ERROR("Forked child process %d exited with code %s" + % (pid, exit_status))) except OSError: # OSError: [Errno 10] No child processes diff --git a/src/plone/app/robotframework/remote.py b/src/plone/app/robotframework/remote.py index f668099..0a630c6 100644 --- a/src/plone/app/robotframework/remote.py +++ b/src/plone/app/robotframework/remote.py @@ -45,7 +45,7 @@ def run_keyword(self, name, args, kwargs={}): result = {'error': '', 'return': ''} try: retval = func(*args, **kwargs) - except Exception, e: + except Exception as e: result['status'] = 'FAIL' result['error'] = str(e) else: diff --git a/src/plone/app/robotframework/robotentrypoints.py b/src/plone/app/robotframework/robotentrypoints.py index d2966a0..9c07d58 100644 --- a/src/plone/app/robotframework/robotentrypoints.py +++ b/src/plone/app/robotframework/robotentrypoints.py @@ -1,9 +1,9 @@ -import sys - +from __future__ import print_function from robot import run_cli from robot import libdoc as ld import pkg_resources +import sys try: pkg_resources.get_distribution('robotframework-ride') @@ -47,7 +47,7 @@ def ride(): from robotide import main main(*sys.argv[1:]) else: - print u"""\ + print(u"""\ Package robotframework-ride was not found. Please, install plone.app.robotframework with proper extras, like: @@ -61,7 +61,7 @@ def ride(): wxPython installed, like: /usr/bin/python bin/ride -""" +""") def libdoc(): diff --git a/src/plone/app/robotframework/saucelabs.py b/src/plone/app/robotframework/saucelabs.py index d2a41a7..15e80f8 100644 --- a/src/plone/app/robotframework/saucelabs.py +++ b/src/plone/app/robotframework/saucelabs.py @@ -1,15 +1,18 @@ # -*- coding: utf-8 -*- -import re -import os -import httplib +from robot.libraries.BuiltIn import BuiltIn +from six.moves.http_client import HTTPConnection + import base64 +import os +import re + + try: import json json # pyflakes except ImportError: import simplejson as json -from robot.libraries.BuiltIn import BuiltIn USERNAME_ACCESS_KEY = re.compile('^(http|https):\/\/([^:]+):([^@]+)@') @@ -39,7 +42,7 @@ def report_sauce_status(self, name, status, tags=[], remote_url=''): 'passed': status == 'PASS', 'tags': tags}) - connection = httplib.HTTPConnection('saucelabs.com') + connection = HTTPConnection('saucelabs.com') connection.request('PUT', '/rest/v1/%s/jobs/%s' % ( username, job_id), body, headers={'Authorization': 'Basic %s' % token} diff --git a/src/plone/app/robotframework/server.py b/src/plone/app/robotframework/server.py index deed6da..76dee39 100644 --- a/src/plone/app/robotframework/server.py +++ b/src/plone/app/robotframework/server.py @@ -1,14 +1,17 @@ # -*- coding: utf-8 -*- +from __future__ import print_function +from plone.app.robotframework.remote import RemoteLibrary +from six.moves.xmlrpc_client import ServerProxy +from six.moves.xmlrpc_server import SimpleXMLRPCServer + import argparse import logging -import select import os +import pkg_resources +import select import sys import time -import xmlrpclib -from SimpleXMLRPCServer import SimpleXMLRPCServer -import pkg_resources try: pkg_resources.get_distribution('watchdog') @@ -19,7 +22,6 @@ from plone.app.robotframework.reload import Watcher HAS_RELOAD = True -from plone.app.robotframework.remote import RemoteLibrary HAS_DEBUG_MODE = False HAS_VERBOSE_CONSOLE = False @@ -36,12 +38,12 @@ def start(zope_layer_dotted_name): - print WAIT("Starting Zope 2 server") + print(WAIT("Starting Zope 2 server")) zsl = Zope2Server() zsl.start_zope_server(zope_layer_dotted_name) - print READY("Started Zope 2 server") + print(READY("Started Zope 2 server")) listener = SimpleXMLRPCServer((LISTENER_HOST, LISTENER_PORT), logRequests=False) @@ -52,19 +54,19 @@ def start(zope_layer_dotted_name): try: listener.serve_forever() finally: - print - print WAIT("Stopping Zope 2 server") + print() + print(WAIT("Stopping Zope 2 server")) zsl.stop_zope_server() - print READY("Zope 2 server stopped") + print(READY("Zope 2 server stopped")) def start_reload(zope_layer_dotted_name, reload_paths=('src',), preload_layer_dotted_name='plone.app.testing.PLONE_FIXTURE', extensions=None): - print WAIT("Starting Zope 2 server") + print(WAIT("Starting Zope 2 server")) zsl = Zope2Server() zsl.start_zope_server(preload_layer_dotted_name) @@ -79,9 +81,9 @@ def start_reload(zope_layer_dotted_name, reload_paths=('src',), forkloop.start() if forkloop.exit: - print WAIT("Stopping Zope 2 server") + print(WAIT("Stopping Zope 2 server")) zsl.stop_zope_server() - print READY("Zope 2 server stopped") + print(READY("Zope 2 server stopped")) return # XXX: For unknown reason call to socket.gethostbyaddr may cause malloc @@ -109,14 +111,14 @@ def start_reload(zope_layer_dotted_name, reload_paths=('src',), if 'Darwin' in platform.uname(): socket.gethostbyaddr = gethostbyaddr - print READY("Zope 2 server started") + print(READY("Zope 2 server started")) try: listener = SimpleXMLRPCServer((LISTENER_HOST, LISTENER_PORT), logRequests=False) except socket.error as e: - print ERROR(str(e)) - print WAIT("Pruning Zope 2 server") + print(ERROR(str(e))) + print(WAIT("Pruning Zope 2 server")) zsl.prune_zope_server() return @@ -131,7 +133,7 @@ def start_reload(zope_layer_dotted_name, reload_paths=('src',), except select.error: # Interrupted system call pass finally: - print WAIT("Pruning Zope 2 server") + print(WAIT("Pruning Zope 2 server")) zsl.prune_zope_server() @@ -196,7 +198,7 @@ class RobotListener: def __init__(self): server_listener_address = 'http://%s:%s' % ( LISTENER_HOST, LISTENER_PORT) - self.server = xmlrpclib.ServerProxy(server_listener_address) + self.server = ServerProxy(server_listener_address) def start_test(self, name, attrs): self.server.zodb_setup() @@ -277,11 +279,11 @@ def zodb_setup(self, layer_dotted_name=None): for layer in layers: if hasattr(layer, 'testSetUp'): if HAS_VERBOSE_CONSOLE: - print WAIT("Test set up {0}.{1}".format( - layer.__module__, layer.__name__)) + print(WAIT("Test set up {0}.{1}".format( + layer.__module__, layer.__name__))) layer.testSetUp() if HAS_VERBOSE_CONSOLE: - print READY("Test set up") + print(READY("Test set up")) def zodb_teardown(self, layer_dotted_name=None): if layer_dotted_name: @@ -293,11 +295,11 @@ def zodb_teardown(self, layer_dotted_name=None): for layer in layers: if hasattr(layer, 'testTearDown'): if HAS_VERBOSE_CONSOLE: - print WAIT("Test tear down {0}.{1}".format( - layer.__module__, layer.__name__)) + print(WAIT("Test tear down {0}.{1}".format( + layer.__module__, layer.__name__))) layer.testTearDown() if HAS_VERBOSE_CONSOLE: - print READY("Test torn down") + print(READY("Test torn down")) setup_layers = {} @@ -312,11 +314,11 @@ def setup_layer(layer, setup_layers=setup_layers): if hasattr(layer, 'setUp'): name = "{0}.{1}".format(layer.__module__, layer.__name__) if HAS_VERBOSE_CONSOLE and name == 'plone.testing.z2.Startup': - print WAIT("Set up {0}.{1} (debug-mode={2})".format( - layer.__module__, layer.__name__, HAS_DEBUG_MODE)) + print(WAIT("Set up {0}.{1} (debug-mode={2})".format( + layer.__module__, layer.__name__, HAS_DEBUG_MODE))) elif HAS_VERBOSE_CONSOLE: - print WAIT("Set up {0}.{1}".format(layer.__module__, - layer.__name__)) + print(WAIT("Set up {0}.{1}".format(layer.__module__, + layer.__name__))) layer.setUp() if HAS_DEBUG_MODE and name == 'plone.testing.z2.Startup': import App.config @@ -338,8 +340,8 @@ def tear_down(setup_layers=setup_layers): try: if hasattr(l, 'tearDown'): if HAS_VERBOSE_CONSOLE: - print WAIT("Tear down {0}.{1}".format(l.__module__, - l.__name__)) + print(WAIT("Tear down {0}.{1}".format(l.__module__, + l.__name__))) l.tearDown() except NotImplementedError: pass diff --git a/src/plone/app/robotframework/testing.py b/src/plone/app/robotframework/testing.py index 3d9c024..b1a267c 100644 --- a/src/plone/app/robotframework/testing.py +++ b/src/plone/app/robotframework/testing.py @@ -5,7 +5,6 @@ re-usable resources of plone.app.robotframework. """ from Acquisition import aq_base -from Products.MailHost.interfaces import IMailHost from plone.app.robotframework.autologin import AutoLogin from plone.app.robotframework.content import Content from plone.app.robotframework.genericsetup import GenericSetup @@ -15,27 +14,33 @@ from plone.app.robotframework.remote import RemoteLibraryLayer from plone.app.robotframework.server import Zope2ServerRemote from plone.app.robotframework.users import Users +from plone.app.testing import applyProfile from plone.app.testing import FunctionalTesting from plone.app.testing import IntegrationTesting from plone.app.testing import PLONE_FIXTURE from plone.app.testing import PloneSandboxLayer -from plone.app.testing import applyProfile from plone.app.testing import ploneSite from plone.testing import Layer from plone.testing import z2 +from Products.MailHost.interfaces import IMailHost +from robot.libraries.BuiltIn import BuiltIn from zope.component import getSiteManager from zope.configuration import xmlconfig + import os import pkg_resources +import six import sys + try: pkg_resources.get_distribution('collective.js.speakjs') except pkg_resources.DistributionNotFound: HAS_SPEAKJS = False else: HAS_SPEAKJS = True -from robot.libraries.BuiltIn import BuiltIn + + class SimplePublicationLayer(Layer): @@ -152,7 +157,7 @@ def _get_robot_variable(self, name): """ if getattr(BuiltIn(), '_context', None) is not None: value = BuiltIn().get_variable_value('${%s}' % name, []) - if isinstance(value, str) or isinstance(value, unicode): + if isinstance(value, str) or isinstance(value, six.text_type): return value.split(',') else: return value