Skip to content

Commit 0ee1c15

Browse files
committed
py- refactoring all the service classes to use a common one.
still needs testing on windows w/ IE & Edge.
1 parent e6f01da commit 0ee1c15

File tree

7 files changed

+184
-386
lines changed

7 files changed

+184
-386
lines changed

py/python.iml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
<sourceFolder url="file://$MODULE_DIR$/selenium" isTestSource="false" />
1212
<sourceFolder url="file://$MODULE_DIR$/test" isTestSource="true" />
1313
</content>
14-
<orderEntry type="jdk" jdkName="Python 2.7" jdkType="Python SDK" />
14+
<orderEntry type="jdk" jdkName="Python 2.7.6 (/usr/bin/python)" jdkType="Python SDK" />
1515
<orderEntry type="sourceFolder" forTests="false" />
1616
</component>
1717
<component name="sonarModuleSettings">

py/selenium/webdriver/chrome/service.py

Lines changed: 6 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,9 @@
1414
# KIND, either express or implied. See the License for the
1515
# specific language governing permissions and limitations
1616
# under the License.
17-
import os
18-
import errno
19-
import subprocess
20-
from subprocess import PIPE
21-
import time
17+
from selenium.webdriver.common import service
2218

23-
from selenium.common.exceptions import WebDriverException
24-
from selenium.webdriver.common import utils
25-
26-
class Service(object):
19+
class Service(service.Service):
2720
"""
2821
Object that manages the starting and stopping of the ChromeDriver
2922
"""
@@ -39,90 +32,12 @@ def __init__(self, executable_path, port=0, service_args=None,
3932
- service_args : List of args to pass to the chromedriver service
4033
- log_path : Path for the chromedriver service to log to"""
4134

42-
self.port = port
43-
self.path = executable_path
4435
self.service_args = service_args or []
4536
if log_path:
4637
self.service_args.append('--log-path=%s' % log_path)
47-
if self.port == 0:
48-
self.port = utils.free_port()
49-
self.env = env
50-
51-
def start(self):
52-
"""
53-
Starts the ChromeDriver Service.
54-
55-
:Exceptions:
56-
- WebDriverException : Raised either when it cannot find the
57-
executable, when it does not have permissions for the
58-
executable, or when it cannot connect to the service.
59-
- Possibly other Exceptions in rare circumstances (OSError, etc).
60-
"""
61-
env = self.env or os.environ
62-
try:
63-
self.process = subprocess.Popen([
64-
self.path,
65-
"--port=%d" % self.port] +
66-
self.service_args, env=env, stdout=PIPE, stderr=PIPE)
67-
except OSError as err:
68-
docs_msg = "Please see " \
69-
"https://sites.google.com/a/chromium.org/chromedriver/home"
70-
if err.errno == errno.ENOENT:
71-
raise WebDriverException(
72-
"'%s' executable needs to be in PATH. %s" % (
73-
os.path.basename(self.path), docs_msg)
74-
)
75-
elif err.errno == errno.EACCES:
76-
raise WebDriverException(
77-
"'%s' executable may have wrong permissions. %s" % (
78-
os.path.basename(self.path), docs_msg)
79-
)
80-
else:
81-
raise
82-
count = 0
83-
while not utils.is_connectable(self.port):
84-
count += 1
85-
time.sleep(1)
86-
if count == 30:
87-
raise WebDriverException("Can not connect to the '" +
88-
os.path.basename(self.path) + "'")
89-
90-
@property
91-
def service_url(self):
92-
"""
93-
Gets the url of the ChromeDriver Service
94-
"""
95-
return "http://localhost:%d" % self.port
96-
97-
def stop(self):
98-
"""
99-
Tells the ChromeDriver to stop and cleans up the process
100-
"""
101-
#If its dead dont worry
102-
if self.process is None:
103-
return
104-
105-
#Tell the Server to die!
106-
try:
107-
from urllib import request as url_request
108-
except ImportError:
109-
import urllib2 as url_request
11038

111-
url_request.urlopen("http://127.0.0.1:%d/shutdown" % self.port)
112-
count = 0
113-
while utils.is_connectable(self.port):
114-
if count == 30:
115-
break
116-
count += 1
117-
time.sleep(1)
39+
service.Service.__init__(self, executable_path, port=port, env=env,
40+
start_error_message="Please see https://sites.google.com/a/chromium.org/chromedriver/home")
11841

119-
#Tell the Server to properly die in case
120-
try:
121-
if self.process:
122-
self.process.stdout.close()
123-
self.process.stderr.close()
124-
self.process.kill()
125-
self.process.wait()
126-
except OSError:
127-
# kill may not be available under windows environment
128-
pass
42+
def command_line_args(self):
43+
return ["--port=%d" % self.port] + self.service_args
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
# Licensed to the Software Freedom Conservancy (SFC) under one
2+
# or more contributor license agreements. See the NOTICE file
3+
# distributed with this work for additional information
4+
# regarding copyright ownership. The SFC licenses this file
5+
# to you under the Apache License, Version 2.0 (the
6+
# "License"); you may not use this file except in compliance
7+
# with the License. You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing,
12+
# software distributed under the License is distributed on an
13+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
# KIND, either express or implied. See the License for the
15+
# specific language governing permissions and limitations
16+
# under the License.
17+
import errno
18+
import os
19+
import platform
20+
import subprocess
21+
from subprocess import PIPE
22+
import time
23+
from selenium.common.exceptions import WebDriverException
24+
from selenium.webdriver.common import utils
25+
26+
class Service(object):
27+
28+
def __init__(self, executable, port=0, log_file=PIPE, env=None, start_error_message=""):
29+
self.path = executable
30+
31+
self.port = port
32+
if self.port == 0:
33+
self.port = utils.free_port()
34+
35+
self.start_error_message = start_error_message
36+
self.log_file = log_file
37+
self.env = env or os.environ
38+
39+
@property
40+
def service_url(self):
41+
"""
42+
Gets the url of the Service
43+
"""
44+
return "http://localhost:%d" % self.port
45+
46+
def command_line_args(self):
47+
raise NotImplemented("This method needs to be implemented in a sub class")
48+
49+
def start(self):
50+
"""
51+
Starts the Service.
52+
53+
:Exceptions:
54+
- WebDriverException : Raised either when it can't start the service
55+
or when it can't connect to the service
56+
"""
57+
try:
58+
cmd = [self.path]
59+
cmd.extend(self.command_line_args())
60+
self.process = subprocess.Popen(cmd, env=self.env,
61+
close_fds=platform.system() != 'Windows',
62+
stdout=self.log_file, stderr=self.log_file)
63+
except TypeError:
64+
raise
65+
except OSError as err:
66+
if err.errno == errno.ENOENT:
67+
raise WebDriverException(
68+
"'%s' executable needs to be in PATH. %s" % (
69+
os.path.basename(self.path), self.start_error_message)
70+
)
71+
elif err.errno == errno.EACCES:
72+
raise WebDriverException(
73+
"'%s' executable may have wrong permissions. %s" % (
74+
os.path.basename(self.path), self.start_error_message)
75+
)
76+
else:
77+
raise
78+
except Exception as e:
79+
raise WebDriverException(
80+
"The executable %s needs to be available in the path. %s\n%s" %
81+
(os.path.basename(self.path), self.start_error_message, str(e))
82+
)
83+
count = 0
84+
while not self.is_connectable():
85+
count += 1
86+
time.sleep(1)
87+
if count == 30:
88+
raise WebDriverException("Can not connect to the Service %s" % self.path)
89+
90+
def is_connectable(self):
91+
return utils.is_connectable(self.port)
92+
93+
def send_remote_shutdown_command(self):
94+
try:
95+
from urllib import request as url_request
96+
except ImportError:
97+
import urllib2 as url_request
98+
99+
url_request.urlopen("http://127.0.0.1:%d/shutdown" % self.port)
100+
count = 0
101+
while self.is_connectable():
102+
if count == 30:
103+
break
104+
count += 1
105+
time.sleep(1)
106+
107+
def stop(self):
108+
"""
109+
Stops the service.
110+
"""
111+
if self.log_file != PIPE:
112+
try:
113+
self.log_file.close()
114+
except Exception:
115+
pass
116+
117+
if self.process is None:
118+
return
119+
120+
self.send_remote_shutdown_command()
121+
122+
try:
123+
if self.process:
124+
self.process.stdout.close()
125+
self.process.stderr.close()
126+
self.process.terminate()
127+
self.process.kill()
128+
self.process.wait()
129+
except OSError:
130+
# kill may not be available under windows environment
131+
pass
132+
133+
def __del__(self):
134+
# subprocess.Popen doesn't send signal on __del__;
135+
# we have to try to stop the launched process.
136+
self.stop()

py/selenium/webdriver/edge/service.py

Lines changed: 8 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -14,86 +14,14 @@
1414
# KIND, either express or implied. See the License for the
1515
# specific language governing permissions and limitations
1616
# under the License.
17-
import subprocess
18-
from subprocess import PIPE
19-
import time
20-
from selenium.common.exceptions import WebDriverException
21-
from selenium.webdriver.common import utils
22-
23-
class Service(object):
24-
"""
25-
Object that manages the starting and stopping of the EdgeDriver
26-
"""
27-
28-
def __init__(self, executable_path, port=0):
29-
"""
30-
Creates a new instance of the Service
31-
32-
:Args:
33-
- executable_path : Path to the EdgeDriver
34-
- port : Port the service is running on
35-
"""
36-
37-
self.path = executable_path
3817

39-
self.port = port
40-
if self.port == 0:
41-
self.port = utils.free_port()
42-
43-
def start(self):
44-
"""
45-
Starts the EdgeDriver Service.
46-
47-
:Exceptions:
48-
- WebDriverException : Raised either when it can't start the service
49-
or when it can't connect to the service
50-
"""
51-
try:
52-
cmd = [self.path, "--port=%d" % self.port]
53-
self.process = subprocess.Popen(cmd,
54-
stdout=PIPE, stderr=PIPE)
55-
except TypeError:
56-
raise
57-
except:
58-
raise WebDriverException(
59-
"The EdgeDriver executable needs to be available in the path. "
60-
"Please download from http://go.microsoft.com/fwlink/?LinkId=619687 ")
61-
count = 0
62-
while not utils.is_connectable(self.port):
63-
count += 1
64-
time.sleep(1)
65-
if count == 30:
66-
raise WebDriverException("Can not connect to the EdgeDriver")
67-
68-
def stop(self):
69-
"""
70-
Tells the EdgeDriver to stop and cleans up the process
71-
"""
72-
#If its dead dont worry
73-
if self.process is None:
74-
return
75-
76-
#Tell the Server to die!
77-
try:
78-
from urllib import request as url_request
79-
except ImportError:
80-
import urllib2 as url_request
18+
from subprocess import PIPE
19+
from selenium.webdriver.common import service
8120

82-
url_request.urlopen("http://127.0.0.1:%d/shutdown" % self.port)
83-
count = 0
84-
while utils.is_connectable(self.port):
85-
if count == 30:
86-
break
87-
count += 1
88-
time.sleep(1)
21+
class Service(service.Service):
22+
def __init__(self, executable_path, port=0, log_file=PIPE):
23+
service.Service.__init__(self, executable_path, port=port, log_file=log_file,
24+
start_error_message="Please download from http://go.microsoft.com/fwlink/?LinkId=619687 ")
8925

90-
#Tell the Server to properly die in case
91-
try:
92-
if self.process:
93-
self.process.stdout.close()
94-
self.process.stderr.close()
95-
self.process.kill()
96-
self.process.wait()
97-
except WindowsError:
98-
# kill may not be available under windows environment
99-
pass
26+
def command_line_args(self):
27+
return ["--port=%d" % self.port]

0 commit comments

Comments
 (0)