Merge lp:~ralsina/ubuntu-sso-client/log-better into lp:ubuntu-sso-client

Proposed by Roberto Alsina
Status: Merged
Approved by: Natalia Bidart
Approved revision: 772
Merged at revision: 764
Proposed branch: lp:~ralsina/ubuntu-sso-client/log-better
Merge into: lp:ubuntu-sso-client
Diff against target: 413 lines (+347/-5)
7 files modified
ubuntu_sso/logger.py (+2/-3)
ubuntu_sso/utils/ui.py (+2/-2)
ubuntu_sso/xdg_base_directory/__init__.py (+40/-0)
ubuntu_sso/xdg_base_directory/tests/__init__.py (+16/-0)
ubuntu_sso/xdg_base_directory/tests/test_common.py (+56/-0)
ubuntu_sso/xdg_base_directory/tests/test_windows.py (+112/-0)
ubuntu_sso/xdg_base_directory/windows.py (+119/-0)
To merge this branch: bzr merge lp:~ralsina/ubuntu-sso-client/log-better
Reviewer Review Type Date Requested Status
Natalia Bidart (community) Approve
Review via email: mp+72573@code.launchpad.net

Commit message

Move the windows xdg implementation from u1-client to sso so we can use it in all our projects.

Description of the change

Move the windows xdg implementation from u1-client to sso so we can use it in all our projects.

To post a comment you must log in.
767. By Roberto Alsina

added the windows-specific tests

Revision history for this message
Natalia Bidart (nataliabidart) wrote :

So, since we're adding a new multiplatform module, we need to come up with something like this:

ubuntu_sso/
    main/
    foo/
    xdg_base_directory/
        __init__.py
        windows.py
        tests/
            __init__.py
            test_common.py <- multiplatform tests
            test_windows.py

review: Needs Fixing
768. By Roberto Alsina

add __init__

769. By Roberto Alsina

forgot one

Revision history for this message
Natalia Bidart (nataliabidart) wrote :

I'm getting all these failures when running ./run-tests:

ubuntu_sso/utils/ui.py:
    121: [E1101, get_data_dir] Module 'ubuntu_sso.xdg_base_directory' has no 'xdg_data_dirs' member

ubuntu_sso/xdg_base_directory/__init__.py:
    24: [C0103] Invalid name "load_config_paths" (should match (([A-Z_][A-Z0-9_]*)|(__.*__))$)
    25: [C0103] Invalid name "save_config_path" (should match (([A-Z_][A-Z0-9_]*)|(__.*__))$)
    26: [C0103] Invalid name "xdg_cache_home" (should match (([A-Z_][A-Z0-9_]*)|(__.*__))$)
    27: [C0103] Invalid name "xdg_data_home" (should match (([A-Z_][A-Z0-9_]*)|(__.*__))$)
    30: [C0103] Invalid name "load_config_paths" (should match (([A-Z_][A-Z0-9_]*)|(__.*__))$)
    31: [C0103] Invalid name "save_config_path" (should match (([A-Z_][A-Z0-9_]*)|(__.*__))$)
    32: [C0103] Invalid name "xdg_cache_home" (should match (([A-Z_][A-Z0-9_]*)|(__.*__))$)
    33: [C0103] Invalid name "xdg_data_home" (should match (([A-Z_][A-Z0-9_]*)|(__.*__))$)
    35: [C0103] Invalid name "ubuntuone_log_dir" (should match (([A-Z_][A-Z0-9_]*)|(__.*__))$)

ubuntu_sso/xdg_base_directory/tests/__init__.py:
    1: [C0111] Missing docstring

ubuntu_sso/xdg_base_directory/windows.py:
    28: [W0621, get_special_folders] Redefining name 'special_folders' from outer scope (line 45)
    23: [C0111, get_special_folders] Missing docstring
    30: [F0401, get_special_folders] Unable to import 'win32com.shell'
    45: [C0103] Invalid name "special_folders" (should match (([A-Z_][A-Z0-9_]*)|(__.*__))$)
    47: [C0103] Invalid name "home_path" (should match (([A-Z_][A-Z0-9_]*)|(__.*__))$)
    48: [C0103] Invalid name "app_local_data_path" (should match (([A-Z_][A-Z0-9_]*)|(__.*__))$)
    49: [C0103] Invalid name "app_global_data_path" (should match (([A-Z_][A-Z0-9_]*)|(__.*__))$)
    52: [C0103] Invalid name "xdg_data_home" (should match (([A-Z_][A-Z0-9_]*)|(__.*__))$)
    62: [C0103] Invalid name "xdg_data_dirs" (should match (([A-Z_][A-Z0-9_]*)|(__.*__))$)
    66: [C0103] Invalid name "xdg_cache_home" (should match (([A-Z_][A-Z0-9_]*)|(__.*__))$)
    70: [C0103] Invalid name "xdg_config_home" (should match (([A-Z_][A-Z0-9_]*)|(__.*__))$)
    81: [C0103] Invalid name "xdg_config_dirs" (should match (([A-Z_][A-Z0-9_]*)|(__.*__))$)
    83: [C0103] Invalid name "xdg_data_dirs" (should match (([A-Z_][A-Z0-9_]*)|(__.*__))$)
    84: [C0103] Invalid name "xdg_config_dirs" (should match (([A-Z_][A-Z0-9_]*)|(__.*__))$)

You may wanna disable C0103 in ubuntu_sso/xdg_base_directory/windows.py and ubuntu_sso/xdg_base_directory/__init__.py.

review: Needs Fixing
Revision history for this message
Natalia Bidart (nataliabidart) wrote :

Another style fix:

* this import from logging.handlers import RotatingFileHandler should be separated by a blank line from the stdlib imports.

review: Needs Fixing
770. By Roberto Alsina

style fix

771. By Roberto Alsina

Lint fixes

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

Pushed with all the lint fixes (and hey, it was missing making xdg_data_dirs visible)

772. By Roberto Alsina

publish missing member, lint fixes

Revision history for this message
Natalia Bidart (nataliabidart) wrote :

Looks good!

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'ubuntu_sso/logger.py'
--- ubuntu_sso/logger.py 2011-01-11 19:13:19 +0000
+++ ubuntu_sso/logger.py 2011-08-23 15:43:28 +0000
@@ -25,12 +25,11 @@
25import os25import os
26import sys26import sys
2727
28import xdg.BaseDirectory
29
30from logging.handlers import RotatingFileHandler28from logging.handlers import RotatingFileHandler
3129
30from ubuntu_sso import xdg_base_directory
3231
33LOGFOLDER = os.path.join(xdg.BaseDirectory.xdg_cache_home, 'sso')32LOGFOLDER = os.path.join(xdg_base_directory.xdg_cache_home, 'sso')
34# create log folder if it doesn't exists33# create log folder if it doesn't exists
35if not os.path.exists(LOGFOLDER):34if not os.path.exists(LOGFOLDER):
36 os.makedirs(LOGFOLDER)35 os.makedirs(LOGFOLDER)
3736
=== modified file 'ubuntu_sso/utils/ui.py'
--- ubuntu_sso/utils/ui.py 2011-07-28 22:50:33 +0000
+++ ubuntu_sso/utils/ui.py 2011-08-23 15:43:28 +0000
@@ -20,10 +20,10 @@
2020
21import os21import os
22import re22import re
23import xdg
24import gettext23import gettext
2524
26from ubuntu_sso.logger import setup_logging25from ubuntu_sso.logger import setup_logging
26from ubuntu_sso import xdg_base_directory
2727
28logger = setup_logging('ubuntu_sso.utils.ui')28logger = setup_logging('ubuntu_sso.utils.ui')
2929
@@ -118,7 +118,7 @@
118 return result118 return result
119119
120 # no local data dir, looking within system data dirs120 # no local data dir, looking within system data dirs
121 data_dirs = xdg.BaseDirectory.xdg_data_dirs121 data_dirs = xdg_base_directory.xdg_data_dirs
122 for path in data_dirs:122 for path in data_dirs:
123 result = os.path.join(path, 'ubuntu-sso-client', 'data')123 result = os.path.join(path, 'ubuntu-sso-client', 'data')
124 result = os.path.abspath(result)124 result = os.path.abspath(result)
125125
=== added directory 'ubuntu_sso/xdg_base_directory'
=== added file 'ubuntu_sso/xdg_base_directory/__init__.py'
--- ubuntu_sso/xdg_base_directory/__init__.py 1970-01-01 00:00:00 +0000
+++ ubuntu_sso/xdg_base_directory/__init__.py 2011-08-23 15:43:28 +0000
@@ -0,0 +1,40 @@
1# Author: Natalia B. Bidart <natalia.bidart@canonical.com>
2#
3# Copyright 2011 Canonical Ltd.
4#
5# This program is free software: you can redistribute it and/or modify it
6# under the terms of the GNU General Public License version 3, as published
7# by the Free Software Foundation.
8#
9# This program is distributed in the hope that it will be useful, but
10# WITHOUT ANY WARRANTY; without even the implied warranties of
11# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
12# PURPOSE. See the GNU General Public License for more details.
13#
14# You should have received a copy of the GNU General Public License along
15# with this program. If not, see <http://www.gnu.org/licenses/>.
16
17"""XDG multiplatform."""
18
19import os
20import sys
21
22# pylint: disable=C0103
23if sys.platform == "win32":
24 from ubuntu_sso.xdg_base_directory import windows
25 load_config_paths = windows.load_config_paths
26 save_config_path = windows.save_config_path
27 xdg_cache_home = windows.xdg_cache_home
28 xdg_data_home = windows.xdg_data_home
29 xdg_data_dirs = windows.xdg_data_dirs
30else:
31 import xdg.BaseDirectory
32 load_config_paths = xdg.BaseDirectory.load_config_paths
33 save_config_path = xdg.BaseDirectory.save_config_path
34 xdg_cache_home = xdg.BaseDirectory.xdg_cache_home
35 xdg_data_home = xdg.BaseDirectory.xdg_data_home
36 xdg_data_dirs = xdg.BaseDirectory.xdg_data_dirs
37
38ubuntuone_log_dir = os.path.join(xdg_cache_home, 'ubuntuone', 'log')
39if not os.path.exists(ubuntuone_log_dir):
40 os.makedirs(ubuntuone_log_dir)
041
=== added directory 'ubuntu_sso/xdg_base_directory/tests'
=== added file 'ubuntu_sso/xdg_base_directory/tests/__init__.py'
--- ubuntu_sso/xdg_base_directory/tests/__init__.py 1970-01-01 00:00:00 +0000
+++ ubuntu_sso/xdg_base_directory/tests/__init__.py 2011-08-23 15:43:28 +0000
@@ -0,0 +1,16 @@
1# ubuntu_sso - Ubuntu Single Sign On client support for desktop apps
2#
3# Copyright 2009-2010 Canonical Ltd.
4#
5# This program is free software: you can redistribute it and/or modify it
6# under the terms of the GNU General Public License version 3, as published
7# by the Free Software Foundation.
8#
9# This program is distributed in the hope that it will be useful, but
10# WITHOUT ANY WARRANTY; without even the implied warranties of
11# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
12# PURPOSE. See the GNU General Public License for more details.
13#
14# You should have received a copy of the GNU General Public License along
15# with this program. If not, see <http://www.gnu.org/licenses/>.
16"""XDG tests."""
017
=== added file 'ubuntu_sso/xdg_base_directory/tests/test_common.py'
--- ubuntu_sso/xdg_base_directory/tests/test_common.py 1970-01-01 00:00:00 +0000
+++ ubuntu_sso/xdg_base_directory/tests/test_common.py 2011-08-23 15:43:28 +0000
@@ -0,0 +1,56 @@
1# -*- coding: utf-8 -*-
2#
3# Authors: Natalia B. Bidart <natalia.bidart@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
19"""Platform independent tests for the XDG constants."""
20
21import os
22
23from twisted.trial.unittest import TestCase
24
25from ubuntu_sso import xdg_base_directory
26
27
28class TestBaseDirectory(TestCase):
29 """Tests for the BaseDirectory module."""
30
31 def test_ubuntuone_log_dir(self):
32 """The ubuntuone_log_dir is correct."""
33 expected = os.path.join(xdg_base_directory.xdg_cache_home,
34 'ubuntuone', 'log')
35 self.assertEqual(expected, xdg_base_directory.ubuntuone_log_dir)
36 self.assertTrue(os.path.exists(expected))
37
38 def test_xdg_cache_home_is_bytes(self):
39 """The returned path is bytes."""
40 actual = xdg_base_directory.xdg_cache_home
41 self.assertIsInstance(actual, str)
42
43 def test_xdg_data_home_is_bytes(self):
44 """The returned path is bytes."""
45 actual = xdg_base_directory.xdg_data_home
46 self.assertIsInstance(actual, str)
47
48 def test_load_config_paths_filter(self):
49 """Since those folders don't exist, this should be empty."""
50 self.assertEqual(list(xdg_base_directory.load_config_paths("x")), [])
51
52 def test_save_config_path(self):
53 """The path should end with xdg_config/x (respecting the separator)."""
54 self.patch(os, "makedirs", lambda *args: None)
55 result = xdg_base_directory.save_config_path("x")
56 self.assertEqual(result.split(os.sep)[-2:], ['xdg_config', 'x'])
057
=== added file 'ubuntu_sso/xdg_base_directory/tests/test_windows.py'
--- ubuntu_sso/xdg_base_directory/tests/test_windows.py 1970-01-01 00:00:00 +0000
+++ ubuntu_sso/xdg_base_directory/tests/test_windows.py 2011-08-23 15:43:28 +0000
@@ -0,0 +1,112 @@
1# -*- coding: utf-8 -*-
2#
3# Authors: Natalia B. Bidart <natalia.bidart@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
19"""Windows-specific tests for the XDG constants."""
20
21import os
22import sys
23
24from twisted.trial.unittest import TestCase
25from ubuntuone.devtools.testcase import skipIfOS
26
27
28# pylint: disable=E1101, E0611, F0401
29if sys.platform == "win32":
30 import win32com.shell
31 from ubuntu_sso.xdg_base_directory.windows import (
32 get_config_dirs,
33 get_data_dirs,
34 get_special_folders,
35 )
36
37
38# pylint: disable=C0103
39class FakeShellConModule(object):
40 """Override CSIDL_ constants."""
41 CSIDL_PROFILE = 0
42 CSIDL_LOCAL_APPDATA = 1
43 CSIDL_COMMON_APPDATA = 2
44
45
46class FakeShellModule(object):
47
48 """Fake Shell Module."""
49
50 def __init__(self):
51 """Set the proper mapping between CSIDL_ consts."""
52 self.values = {
53 0: u'c:\\path\\to\\users\\home',
54 1: u'c:\\path\\to\\users\\home\\appData\\local',
55 2: u'c:\\programData',
56 }
57
58 def SHGetFolderPath(self, dummy0, shellconValue, dummy2, dummy3):
59 """Override SHGetFolderPath functionality."""
60 return self.values[shellconValue]
61
62
63@skipIfOS('linux2', 'Windows-specific tests.')
64class TestBaseDirectoryWindows(TestCase):
65 """Tests for the BaseDirectory module."""
66
67 def test_get_special_folders(self):
68 """Make sure we can import the platform module."""
69
70 shellModule = FakeShellModule()
71 self.patch(win32com.shell, "shell", shellModule)
72 self.patch(win32com.shell, "shellcon", FakeShellConModule())
73 special_folders = get_special_folders()
74 self.assertTrue('Personal' in special_folders)
75 self.assertTrue('Local AppData' in special_folders)
76 self.assertTrue('AppData' in special_folders)
77 self.assertTrue('Common AppData' in special_folders)
78
79 self.assertTrue(special_folders['Personal'] == \
80 shellModule.values[FakeShellConModule.CSIDL_PROFILE])
81 self.assertTrue(special_folders['Local AppData'] == \
82 shellModule.values[FakeShellConModule.CSIDL_LOCAL_APPDATA])
83 self.assertTrue(special_folders['Local AppData'].startswith(
84 special_folders['AppData']))
85 self.assertTrue(special_folders['Common AppData'] == \
86 shellModule.values[FakeShellConModule.CSIDL_COMMON_APPDATA])
87
88 # Can't use assert_syncdaemon_path
89 for val in special_folders.itervalues():
90 self.assertIsInstance(val, str)
91 val.decode('utf8')
92 # Should not raise exceptions
93
94 def test_get_data_dirs(self):
95 """Check thet get_data_dirs uses pathsep correctly."""
96 bad_sep = filter(lambda x: x not in os.pathsep, ":;")
97 dir_list = ["A", "B", bad_sep, "C"]
98 self.patch(os, "environ",
99 dict(XDG_DATA_DIRS=os.pathsep.join(
100 dir_list)))
101 dirs = get_data_dirs()
102 self.assertEqual(dirs, dir_list)
103
104 def test_get_config_dirs(self):
105 """Check thet get_data_dirs uses pathsep correctly."""
106 bad_sep = filter(lambda x: x not in os.pathsep, ":;")
107 dir_list = ["A", "B", bad_sep, "C"]
108 self.patch(os, "environ",
109 dict(XDG_CONFIG_DIRS=os.pathsep.join(
110 dir_list)))
111 dirs = get_config_dirs()[1:]
112 self.assertEqual(dirs, dir_list)
0113
=== added file 'ubuntu_sso/xdg_base_directory/windows.py'
--- ubuntu_sso/xdg_base_directory/windows.py 1970-01-01 00:00:00 +0000
+++ ubuntu_sso/xdg_base_directory/windows.py 2011-08-23 15:43:28 +0000
@@ -0,0 +1,119 @@
1# Authors: Manuel de la Pena <manuel@canonical.com>
2# Diego Sarmentero <diego.sarmentero@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
18"""XDG helpers for windows."""
19
20import os
21
22
23# pylint: disable=C0103
24def get_special_folders():
25 """ Routine to grab all the Windows Special Folders locations.
26
27 If successful, returns dictionary
28 of shell folder locations indexed on Windows keyword for each;
29 otherwise, returns an empty dictionary.
30 """
31 # pylint: disable=W0621, F0401, E0611
32 special_folders = {}
33
34 from win32com.shell import shell, shellcon
35 # CSIDL_LOCAL_APPDATA = C:\Users\<username>\AppData\Local
36 # CSIDL_PROFILE = C:\Users\<username>
37 # CSIDL_COMMON_APPDATA = C:\ProgramData
38 # More information on these at
39 # http://msdn.microsoft.com/en-us/library/bb762494(v=vs.85).aspx
40 get_path = lambda name: shell.SHGetFolderPath(
41 0, getattr(shellcon, name), None, 0).encode('utf8')
42 special_folders['Personal'] = get_path("CSIDL_PROFILE")
43 special_folders['Local AppData'] = get_path("CSIDL_LOCAL_APPDATA")
44 special_folders['AppData'] = os.path.dirname(
45 special_folders['Local AppData'])
46 special_folders['Common AppData'] = get_path("CSIDL_COMMON_APPDATA")
47 return special_folders
48
49special_folders = get_special_folders()
50
51home_path = special_folders['Personal']
52app_local_data_path = special_folders['Local AppData']
53app_global_data_path = special_folders['Common AppData']
54
55# use the non roaming app data
56xdg_data_home = os.environ.get('XDG_DATA_HOME',
57 os.path.join(app_local_data_path, 'xdg'))
58
59
60def get_data_dirs():
61 """Returns XDG data directories."""
62 return os.environ.get('XDG_DATA_DIRS',
63 '{0}{1}{2}'.format(app_local_data_path, os.pathsep,
64 app_global_data_path)).split(os.pathsep)
65
66xdg_data_dirs = get_data_dirs()
67
68# we will return the roaming data wich is as close as we get in windows
69# regarding caching.
70xdg_cache_home = os.environ.get('XDG_CACHE_HOME',
71 os.path.join(xdg_data_home, 'cache'))
72
73# point to the not roaming app data for the user
74xdg_config_home = os.environ.get('XDG_CONFIG_HOME',
75 app_local_data_path)
76
77
78def get_config_dirs():
79 """Return XDG config directories."""
80 return [xdg_config_home] + \
81 os.environ.get('XDG_CONFIG_DIRS',
82 app_global_data_path,
83 ).split(os.pathsep)
84
85xdg_config_dirs = get_config_dirs()
86
87xdg_data_dirs = filter(lambda x: x, xdg_data_dirs)
88xdg_config_dirs = filter(lambda x: x, xdg_config_dirs)
89
90
91def load_config_paths(*resource):
92 """Iterator of configuration paths.
93
94 Return an iterator which gives each directory named 'resource' in
95 the configuration search path. Information provided by earlier
96 directories should take precedence over later ones (ie, the user's
97 config dir comes first).
98 """
99 resource = os.path.join(*resource)
100 for config_dir in xdg_config_dirs:
101 path = os.path.join(config_dir, resource)
102 if os.path.exists(path):
103 yield path
104
105
106def save_config_path(*resource):
107 """Path to save configuration.
108
109 Ensure $XDG_CONFIG_HOME/<resource>/ exists, and return its path.
110 'resource' should normally be the name of your application. Use this
111 when SAVING configuration settings. Use the xdg_config_dirs variable
112 for loading.
113 """
114 resource = os.path.join(*resource)
115 assert not resource.startswith('/')
116 path = os.path.join(xdg_config_home, resource)
117 if not os.path.isdir(path):
118 os.makedirs(path, 0700)
119 return path

Subscribers

People subscribed via source and target branches