Merge lp:~mandel/ubuntu-sso-client/implement_windows_networkstatus into lp:ubuntu-sso-client

Proposed by Manuel de la Peña
Status: Merged
Approved by: Manuel de la Peña
Approved revision: 689
Merged at revision: 678
Proposed branch: lp:~mandel/ubuntu-sso-client/implement_windows_networkstatus
Merge into: lp:ubuntu-sso-client
Prerequisite: lp:~mandel/ubuntu-sso-client/implement_windows_keyring
Diff against target: 455 lines (+382/-9)
8 files modified
run-tests (+1/-1)
run-tests.bat (+2/-2)
ubuntu_sso/networkstate/__init__.py (+40/-0)
ubuntu_sso/networkstate/windows.py (+197/-0)
ubuntu_sso/tests/bin/show_nm_state (+1/-1)
ubuntu_sso/tests/networkstate/__init__.py (+17/-0)
ubuntu_sso/tests/networkstate/test_linux_networkstate.py (+5/-5)
ubuntu_sso/tests/networkstate/test_windows_networkstate.py (+119/-0)
To merge this branch: bzr merge lp:~mandel/ubuntu-sso-client/implement_windows_networkstatus
Reviewer Review Type Date Requested Status
Roberto Alsina (community) Approve
Alejandro J. Cura (community) linux Approve
Review via email: mp+52091@code.launchpad.net

Commit message

Added the network status implementation for windows.

Description of the change

Added the network status implementation for windows.

To post a comment you must log in.
Revision history for this message
Alejandro J. Cura (alecu) wrote :

Launchpad shows this message: "Conflict adding file run-tests.bat. Moved existing file to run-tests.bat.moved."

This also happens when merging by hand.

Found a few typos (many!):
 * "nameing" -> "naming"
 * "deliberated because we are follwoing" -> "deliberate because we are following"
 * "For more ingo" -> "For more info"
 * "to run in an other" -> "to run in another"
 * "listent" -> "listen"
 * "the machine s connected" -> "the machine is connected"
 * "literner_thread" -> "listener_thread" (more than one replacement)

Otherwise the code looks fine.

review: Needs Fixing
Revision history for this message
Alejandro J. Cura (alecu) wrote :

The "literner" variable name typo is still present in some of the tests.

The really weird thing is that all tests pass, yet this error is only catched by the lint step:

ubuntu_sso/tests/networkstate/test_windows_networkstate.py:
    107: [E1123, TestNetworkManagerState.test_find_online_state_not_connected] Passing unexpected keyword argument 'literner_thread' in function call
    118: [E1123, TestNetworkManagerState.test_find_online_state_connected] Passing unexpected keyword argument 'literner_thread' in function call

review: Needs Fixing
Revision history for this message
Alejandro J. Cura (alecu) wrote :

Ran tests on Linux, detailed review of the code, looking good.

review: Approve (linux)
Revision history for this message
Roberto Alsina (ralsina) wrote :

+1

review: Approve
Revision history for this message
Ubuntu One Auto Pilot (otto-pilot) wrote :
689. By Manuel de la Peña

Merged with implement_windows_keyring and fixed conflicts.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'run-tests'
--- run-tests 2010-12-20 15:39:23 +0000
+++ run-tests 2011-03-15 08:28:29 +0000
@@ -33,5 +33,5 @@
33}33}
3434
35echo "Running test suite for ""$MODULE"35echo "Running test suite for ""$MODULE"
36`which xvfb-run` u1trial "$MODULE" && style_check36`which xvfb-run` u1trial "$MODULE" -i "test_windows_networkstate.py" && style_check
37rm -rf _trial_temp37rm -rf _trial_temp
3838
=== modified file 'run-tests.bat'
--- run-tests.bat 2011-03-15 08:28:29 +0000
+++ run-tests.bat 2011-03-15 08:28:29 +0000
@@ -51,8 +51,8 @@
51:PYTHONPRESENT51:PYTHONPRESENT
52ECHO Python found, executing the tests...52ECHO Python found, executing the tests...
53:: execute the tests with a number of ignored linux only modules53:: execute the tests with a number of ignored linux only modules
54"%PYTHONPATH%\python.exe" "%PYTHONPATH%\Scripts\u1trial" -c ubuntu_sso -i "test_gui.py, test_linux_keyring.py"54"%PYTHONPATH%\python.exe" "%PYTHONPATH%\Scripts\u1trial" -c ubuntu_sso -i "test_gui.py, test_linux_keyring.py, test_linux_network_state.py"
55"%PYTHONPATH%\python.exe" "%PYTHONPATH%\Scripts\u1lint"55"%PYTHONPATH%\python.exe" "%PYTHONPATH%\Scripts\u1lint" ubuntu_sso
56:: test for style if we can, if pep8 is not present, move to the end56:: test for style if we can, if pep8 is not present, move to the end
57IF EXIST "%PYTHONPATH%Scripts\pep8.exe"57IF EXIST "%PYTHONPATH%Scripts\pep8.exe"
58"%PYTHONPATH%\Scripts\pep8.exe" --repeat ubuntu_sso58"%PYTHONPATH%\Scripts\pep8.exe" --repeat ubuntu_sso
5959
=== added directory 'ubuntu_sso/networkstate'
=== added file 'ubuntu_sso/networkstate/__init__.py'
--- ubuntu_sso/networkstate/__init__.py 1970-01-01 00:00:00 +0000
+++ ubuntu_sso/networkstate/__init__.py 2011-03-15 08:28:29 +0000
@@ -0,0 +1,40 @@
1# -*- coding: utf-8 -*-
2# Author: Manuel de la Pena <manuel@canonical.com>
3#
4# Copyright 2011 Canonical Ltd.
5#
6# This program is free software: you can redistribute it and/or modify it
7# under the terms of the GNU General Public License version 3, as published
8# by the Free Software Foundation.
9#
10# This program is distributed in the hope that it will be useful, but
11# WITHOUT ANY WARRANTY; without even the implied warranties of
12# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
13# PURPOSE. See the GNU General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License along
16# with this program. If not, see <http://www.gnu.org/licenses/>.
17"""Platform specific network status."""
18
19import sys
20
21# ignore global naming issues.
22# pylint: disable=C0103
23
24NetworkManagerState = None
25ONLINE = None
26OFFLINE = None
27UNKNOWN = None
28
29if sys.platform == 'win32':
30 from ubuntu_sso.networkstate import windows
31 NetworkManagerState = windows.NetworkManagerState
32 ONLINE = windows.ONLINE
33 OFFLINE = windows.OFFLINE
34 UNKNOWN = windows.UNKNOWN
35else:
36 from ubuntu_sso.networkstate import linux
37 NetworkManagerState = linux.NetworkManagerState
38 ONLINE = linux.ONLINE
39 OFFLINE = linux.OFFLINE
40 UNKNOWN = linux.UNKNOWN
041
=== renamed file 'ubuntu_sso/networkstate.py' => 'ubuntu_sso/networkstate/linux.py'
=== added file 'ubuntu_sso/networkstate/windows.py'
--- ubuntu_sso/networkstate/windows.py 1970-01-01 00:00:00 +0000
+++ ubuntu_sso/networkstate/windows.py 2011-03-15 08:28:29 +0000
@@ -0,0 +1,197 @@
1# -*- coding: utf-8 -*-
2# Author: Manuel de la Pena <manuel@canonical.com>
3#
4# Copyright 2011 Canonical Ltd.
5#
6# This program is free software: you can redistribute it and/or modify it
7# under the terms of the GNU General Public License version 3, as published
8# by the Free Software Foundation.
9#
10# This program is distributed in the hope that it will be useful, but
11# WITHOUT ANY WARRANTY; without even the implied warranties of
12# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
13# PURPOSE. See the GNU General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License along
16# with this program. If not, see <http://www.gnu.org/licenses/>.
17"""Network status implementation on Windows."""
18
19# pylint: disable=F0401
20import pythoncom
21# pylint: enable=F0401
22
23from ctypes import windll, byref
24from ctypes.wintypes import DWORD
25from threading import Thread
26# pylint: disable=F0401
27from win32com.server.policy import DesignatedWrapPolicy
28from win32com.client import Dispatch
29# pylint: enable=F0401
30
31from ubuntu_sso.logger import setup_logging
32
33logger = setup_logging("ubuntu_sso.networkstate")
34
35# naming errors are deliberated because we are following the COM naming to make
36# it clear for later developers.
37# pylint: disable=C0103
38
39# Values returned by the callback
40ONLINE, OFFLINE, UNKNOWN = object(), object(), object()
41
42## from EventSys.h
43PROGID_EventSystem = "EventSystem.EventSystem"
44PROGID_EventSubscription = "EventSystem.EventSubscription"
45
46# SENS (System Event Notification Service) values for the events,
47# this events contain the uuid of the event, the name of the event to be used
48# as well as the method name of the method in the ISesNetwork interface that
49# will be executed for the event.
50# For more info look at:
51# http://msdn.microsoft.com/en-us/library/aa377384(v=vs.85).aspx
52
53SUBSCRIPTION_NETALIVE = ('{cd1dcbd6-a14d-4823-a0d2-8473afde360f}',
54 'UbuntuOne Network Alive',
55 'ConnectionMade')
56
57SUBSCRIPTION_NETALIVE_NOQOC = ('{a82f0e80-1305-400c-ba56-375ae04264a1}',
58 'UbuntuOne Net Alive No Info',
59 'ConnectionMadeNoQOCInfo')
60
61SUBSCRIPTION_NETLOST = ('{45233130-b6c3-44fb-a6af-487c47cee611}',
62 'UbuntuOne Network Lost',
63 'ConnectionLost')
64
65SUBSCRIPTION_REACH = ('{4c6b2afa-3235-4185-8558-57a7a922ac7b}',
66 'UbuntuOne Network Reach',
67 'ConnectionMade')
68
69SUBSCRIPTION_REACH_NOQOC = ('{db62fa23-4c3e-47a3-aef2-b843016177cf}',
70 'UbuntuOne Network Reach No Info',
71 'ConnectionMadeNoQOCInfo')
72
73SUBSCRIPTION_REACH_NOQOC2 = ('{d4d8097a-60c6-440d-a6da-918b619ae4b7}',
74 'UbuntuOne Network Reach No Info 2',
75 'ConnectionMadeNoQOCInfo')
76
77SUBSCRIPTIONS = [SUBSCRIPTION_NETALIVE,
78 SUBSCRIPTION_NETALIVE_NOQOC,
79 SUBSCRIPTION_NETLOST,
80 SUBSCRIPTION_REACH,
81 SUBSCRIPTION_REACH_NOQOC,
82 SUBSCRIPTION_REACH_NOQOC2]
83
84SENSGUID_EVENTCLASS_NETWORK = '{d5978620-5b9f-11d1-8dd2-00aa004abd5e}'
85SENSGUID_PUBLISHER = "{5fee1bd6-5b9b-11d1-8dd2-00aa004abd5e}"
86
87# uuid of the implemented com interface
88IID_ISesNetwork = '{d597bab1-5b9f-11d1-8dd2-00aa004abd5e}'
89
90
91class NetworkManager(DesignatedWrapPolicy):
92 """Implement ISesNetwork to know about the network status."""
93
94 _com_interfaces_ = [IID_ISesNetwork]
95 _public_methods_ = ['ConnectionMade',
96 'ConnectionMadeNoQOCInfo',
97 'ConnectionLost']
98 _reg_clsid_ = '{41B032DA-86B5-4907-A7F7-958E59333010}'
99 _reg_progid_ = "UbuntuOne.NetworkManager"
100
101 def __init__(self, connected_cb=None, connected_cb_info=None,
102 disconnected_cb=None):
103 # pylint: disable=E1101
104 self._wrap_(self)
105 # pylint: enable=E1101
106 self.connected_cb = connected_cb
107 self.connected_cb_info = connected_cb_info
108 self.disconnected_cb = disconnected_cb
109
110 def ConnectionMade(self, *args):
111 """Tell that the connection is up again."""
112 logger.info('Connection was made.')
113 if self.connected_cb_info:
114 self.connected_cb_info()
115
116 def ConnectionMadeNoQOCInfo(self, *args):
117 """Tell that the connection is up again."""
118 logger.info('Connection was made no info.')
119 if self.connected_cb:
120 self.connected_cb()
121
122 def ConnectionLost(self, *args):
123 """Tell the connection was lost."""
124 logger.info('Connection was lost.')
125 if self.disconnected_cb:
126 self.disconnected_cb()
127
128 def register(self):
129 """Register to listen to network events."""
130 # call the CoInitialize to allow the registration to run in another
131 # thread
132 pythoncom.CoInitialize()
133 # interface to be used by com
134 manager_interface = pythoncom.WrapObject(self)
135 event_system = Dispatch(PROGID_EventSystem)
136 # register to listen to each of the events to make sure that
137 # the code will work on all platforms.
138 for current_event in SUBSCRIPTIONS:
139 # create an event subscription and add it to the event
140 # service
141 event_subscription = Dispatch(PROGID_EventSubscription)
142 event_subscription.EventClassId = SENSGUID_EVENTCLASS_NETWORK
143 event_subscription.PublisherID = SENSGUID_PUBLISHER
144 event_subscription.SubscriptionID = current_event[0]
145 event_subscription.SubscriptionName = current_event[1]
146 event_subscription.MethodName = current_event[2]
147 event_subscription.SubscriberInterface = manager_interface
148 event_subscription.PerUser = True
149 # store the event
150 try:
151 event_system.Store(PROGID_EventSubscription,
152 event_subscription)
153 except pythoncom.com_error as e:
154 logger.error(
155 'Error registering %s to event %s', e, current_event[1])
156
157 pythoncom.PumpMessages()
158
159
160def is_machine_connected():
161 """Return if the machine is connected to the internet."""
162 wininet = windll.wininet
163 flags = DWORD()
164 connected = wininet.InternetGetConnectedState(byref(flags), None)
165 return connected == 1
166
167
168class NetworkManagerState(object):
169 """Check for status changed in the network on Windows."""
170
171 def __init__(self, result_cb, **kwargs):
172 """Initialize this instance with a result and error callbacks."""
173 self.result_cb = result_cb
174
175 def connection_made(self):
176 """Return the connection state over the call back."""
177 self.result_cb(ONLINE)
178
179 def connection_lost(self):
180 """Return the connection was lost over the call back."""
181 self.result_cb(OFFLINE)
182
183 def find_online_state(self, listener=None, listener_thread=None):
184 """Get the network state and return it thru the set callback."""
185 # check the current status right now
186 if is_machine_connected():
187 self.result_cb(ONLINE)
188 else:
189 self.result_cb(OFFLINE)
190 if listener is None:
191 # start listening for network changes
192 listener = NetworkManager(connected_cb=self.connection_made,
193 disconnected_cb=self.connection_lost)
194 if listener_thread is None:
195 listener_thread = Thread(target=listener.register,
196 name='Ubuntu SSO NetworkManager')
197 listener_thread.start()
0198
=== modified file 'ubuntu_sso/tests/bin/show_nm_state'
--- ubuntu_sso/tests/bin/show_nm_state 2010-12-20 14:29:18 +0000
+++ ubuntu_sso/tests/bin/show_nm_state 2011-03-15 08:28:29 +0000
@@ -23,7 +23,7 @@
2323
24from dbus.mainloop.glib import DBusGMainLoop24from dbus.mainloop.glib import DBusGMainLoop
2525
26from ubuntu_sso.networkstate import NetworkManagerState, NM_STATE_NAMES26from ubuntu_sso.networkstate.linux import NetworkManagerState, NM_STATE_NAMES
2727
28DBusGMainLoop(set_as_default=True)28DBusGMainLoop(set_as_default=True)
2929
3030
=== added directory 'ubuntu_sso/tests/networkstate'
=== added file 'ubuntu_sso/tests/networkstate/__init__.py'
--- ubuntu_sso/tests/networkstate/__init__.py 1970-01-01 00:00:00 +0000
+++ ubuntu_sso/tests/networkstate/__init__.py 2011-03-15 08:28:29 +0000
@@ -0,0 +1,17 @@
1# -*- coding: utf-8 -*-
2# Author: Manuel de la Pena <manuel@canonical.com>
3#
4# Copyright 2011 Canonical Ltd.
5#
6# This program is free software: you can redistribute it and/or modify it
7# under the terms of the GNU General Public License version 3, as published
8# by the Free Software Foundation.
9#
10# This program is distributed in the hope that it will be useful, but
11# WITHOUT ANY WARRANTY; without even the implied warranties of
12# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
13# PURPOSE. See the GNU General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License along
16# with this program. If not, see <http://www.gnu.org/licenses/>.
17"""Test the different networkstatus implementations."""
018
=== renamed file 'ubuntu_sso/tests/test_networkstate.py' => 'ubuntu_sso/tests/networkstate/test_linux_networkstate.py'
--- ubuntu_sso/tests/test_networkstate.py 2010-09-30 18:57:38 +0000
+++ ubuntu_sso/tests/networkstate/test_linux_networkstate.py 2011-03-15 08:28:29 +0000
@@ -20,11 +20,11 @@
20"""Tests for the network state detection code."""20"""Tests for the network state detection code."""
2121
22from ubuntu_sso.networkstate import (NetworkManagerState,22from ubuntu_sso.networkstate import (NetworkManagerState,
23 DBUS_UNKNOWN_SERVICE,23 ONLINE, OFFLINE, UNKNOWN)
24 ONLINE, OFFLINE, UNKNOWN,24from ubuntu_sso.networkstate.linux import (DBUS_UNKNOWN_SERVICE,
25 NM_STATE_DISCONNECTED,25 NM_STATE_DISCONNECTED,
26 NM_STATE_CONNECTING,26 NM_STATE_CONNECTING,
27 NM_STATE_CONNECTED)27 NM_STATE_CONNECTED)
2828
29from mocker import ARGS, KWARGS, ANY, MockerTestCase29from mocker import ARGS, KWARGS, ANY, MockerTestCase
3030
3131
=== added file 'ubuntu_sso/tests/networkstate/test_windows_networkstate.py'
--- ubuntu_sso/tests/networkstate/test_windows_networkstate.py 1970-01-01 00:00:00 +0000
+++ ubuntu_sso/tests/networkstate/test_windows_networkstate.py 2011-03-15 08:28:29 +0000
@@ -0,0 +1,119 @@
1# -*- coding: utf-8 -*-
2#
3# Author: Manuel de la Pena<manuel@canonical.com>
4#
5# Copyright 2011 Canonical Ltd.
6#
7# This program is free software: you can redistribute it and/or modify it
8# under the terms of the GNU General Public License version 3, as published
9# by the Free Software Foundation.
10#
11# This program is distributed in the hope that it will be useful, but
12# WITHOUT ANY WARRANTY; without even the implied warranties of
13# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
14# PURPOSE. See the GNU General Public License for more details.
15#
16# You should have received a copy of the GNU General Public License along
17# with this program. If not, see <http://www.gnu.org/licenses/>.
18"""Tests for the network manager."""
19from mocker import MockerTestCase
20from ubuntu_sso.networkstate.windows import (
21 NetworkManager,
22 NetworkManagerState,
23 ONLINE,
24 OFFLINE)
25
26
27class TestNetworkManager(MockerTestCase):
28 """Test he Network Manager."""
29
30 def setUp(self):
31 super(TestNetworkManager, self).setUp()
32 self.connection_info = self.mocker.mock()
33 self.connection_no_info = self.mocker.mock()
34 self.disconnected = self.mocker.mock()
35 self.manager = NetworkManager(self.connection_no_info,
36 self.connection_info, self.disconnected)
37
38 def test_connection_made(self):
39 """Ensure db is called."""
40 self.connection_info()
41 self.mocker.replay()
42 self.manager.ConnectionMade()
43
44 def test_connection_made_no_cb(self):
45 """Ensure db is called."""
46 self.manager.connected_cb_info = None
47 self.mocker.replay()
48 self.manager.ConnectionMade()
49
50 def test_connection_made_no_info(self):
51 """Ensure db is called."""
52 self.connection_no_info()
53 self.mocker.replay()
54 self.manager.ConnectionMadeNoQOCInfo()
55
56 def test_connection_made_no_info_no_cb(self):
57 """Ensure db is called."""
58 self.manager.connected_cb = None
59 self.mocker.replay()
60 self.manager.ConnectionMadeNoQOCInfo()
61
62 def test_disconnection(self):
63 """Ensure db is called."""
64 self.disconnected()
65 self.mocker.replay()
66 self.manager.ConnectionLost()
67
68 def test_disconnection_no_cb(self):
69 """Ensure db is called."""
70 self.manager.disconnected_cb = None
71 self.mocker.replay()
72 self.manager.ConnectionLost()
73
74
75class TestNetworkManagerState(MockerTestCase):
76 """Test he Network Manager State."""
77
78 def setUp(self):
79 super(TestNetworkManagerState, self).setUp()
80 self.network_manager = self.mocker.mock()
81 self.is_connected = self.mocker.replace(
82 'ubuntu_sso.networkstate.windows.is_machine_connected')
83 self.thread = self.mocker.mock()
84 self.cb = self.mocker.mock()
85 self.state = NetworkManagerState(self.cb)
86
87 def test_connection_made(self):
88 """Test that the cb is actually called."""
89 self.cb(ONLINE)
90 self.mocker.replay()
91 self.state.connection_made()
92
93 def test_connection_lost(self):
94 """Test that the cb is actually called."""
95 self.cb(OFFLINE)
96 self.mocker.replay()
97 self.state.connection_lost()
98
99 def test_find_online_state_not_connected(self):
100 """Test that we do find the online state correctly."""
101 self.is_connected()
102 self.mocker.result(False)
103 self.cb(OFFLINE)
104 self.mocker.result(self.thread)
105 self.thread.start()
106 self.mocker.replay()
107 self.state.find_online_state(listener=self.network_manager,
108 listener_thread=self.thread)
109
110 def test_find_online_state_connected(self):
111 """Test that we do find the online state correctly."""
112 self.is_connected()
113 self.mocker.result(ONLINE)
114 self.cb(ONLINE)
115 self.mocker.result(self.thread)
116 self.thread.start()
117 self.mocker.replay()
118 self.state.find_online_state(listener=self.network_manager,
119 listener_thread=self.thread)

Subscribers

People subscribed via source and target branches