~onboard/onboard/0.99

« back to all changes in this revision

Viewing changes to Onboard/utils.py

  • Committer: marmuta
  • Date: 2013-08-18 18:00:28 UTC
  • Revision ID: marmvta@gmail.com-20130818180028-xdhfvw3i220volz2
Support XDG Base Directory Specification (LP: #1074448).

Onboard's data directory moves from ~/.onboard to the XDG data directory,
which will usually be ~/.local/share/onboard.
Existing data in either ~/.onboard or ~/.sok is migrated to the new location.

System defaults are looked up in XDG_CONFIG_HOME, XDG_CONFIG_DIRS and the
previous locations, in this order.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1253
1253
            return True
1254
1254
    return False
1255
1255
 
 
1256
def chmodtree(path, mode = 0o777, only_dirs = False):
 
1257
    """
 
1258
    Change permissions of all files of the given directory tree.
 
1259
    Raises OSError.
 
1260
    """
 
1261
    os.chmod(path, mode)
 
1262
    for root, dirs, files in os.walk(path):
 
1263
        for d in dirs:
 
1264
            os.chmod(os.path.join(root, d), mode)                    
 
1265
        if not only_dirs:
 
1266
            for f in files:
 
1267
                os.chmod(os.path.join(root, f), mode)                    
 
1268
 
1256
1269
def unicode_str(obj, encoding = "utf-8"):
1257
1270
    """
1258
1271
    Safe str() function that always returns an unicode string.
1415
1428
        perms.append(m)
1416
1429
    return perms
1417
1430
 
 
1431
 
 
1432
class XDGDirs:
 
1433
    """
 
1434
    Build paths compliant with XDG Base Directory Specification.
 
1435
    http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html
 
1436
 
 
1437
    Doctests:
 
1438
 
 
1439
    >>> os.environ["HOME"] = "/home/test_user"
 
1440
 
 
1441
    # XDG_CONFIG_HOME unavailable
 
1442
    >>> os.environ["XDG_CONFIG_HOME"] = ""
 
1443
    >>> XDGDirs.get_config_home("onboard/test.dat")
 
1444
    '/home/test_user/.config/onboard/test.dat'
 
1445
 
 
1446
    # XDG_CONFIG_HOME available
 
1447
    >>> os.environ["XDG_CONFIG_HOME"] = "/home/test_user/.config_home"
 
1448
    >>> XDGDirs.get_config_home("onboard/test.dat")
 
1449
    '/home/test_user/.config_home/onboard/test.dat'
 
1450
 
 
1451
    # XDG_DATA_HOME unavailable
 
1452
    >>> os.environ["XDG_DATA_HOME"] = ""
 
1453
    >>> XDGDirs.get_data_home("onboard/test.dat")
 
1454
    '/home/test_user/.local/share/onboard/test.dat'
 
1455
 
 
1456
    # XDG_DATA_HOME available
 
1457
    >>> os.environ["XDG_DATA_HOME"] = "/home/test_user/.data_home"
 
1458
    >>> XDGDirs.get_data_home("onboard/test.dat")
 
1459
    '/home/test_user/.data_home/onboard/test.dat'
 
1460
 
 
1461
    # XDG_CONFIG_DIRS unvailable
 
1462
    >>> os.environ["XDG_CONFIG_HOME"] = ""
 
1463
    >>> os.environ["XDG_CONFIG_DIRS"] = ""
 
1464
    >>> XDGDirs.get_all_config_dirs("onboard/test.dat")
 
1465
    ['/home/test_user/.config/onboard/test.dat', '/etc/xdg/onboard/test.dat']
 
1466
 
 
1467
    # XDG_CONFIG_DIRS available
 
1468
    >>> os.environ["XDG_CONFIG_HOME"] = ""
 
1469
    >>> os.environ["XDG_CONFIG_DIRS"] = "/etc/xdg/xdg-ubuntu:/etc/xdg"
 
1470
    >>> XDGDirs.get_all_config_dirs("onboard/test.dat")
 
1471
    ['/home/test_user/.config/onboard/test.dat', \
 
1472
'/etc/xdg/xdg-ubuntu/onboard/test.dat', \
 
1473
'/etc/xdg/onboard/test.dat']
 
1474
 
 
1475
    # XDG_DATA_DIRS unvailable
 
1476
    >>> os.environ["XDG_DATA_HOME"] = ""
 
1477
    >>> os.environ["XDG_DATA_DIRS"] = ""
 
1478
    >>> XDGDirs.get_all_data_dirs("onboard/test.dat")
 
1479
    ['/home/test_user/.local/share/onboard/test.dat', \
 
1480
'/usr/local/share/onboard/test.dat', \
 
1481
'/usr/share/onboard/test.dat']
 
1482
 
 
1483
    # XDG_DATA_DIRS available
 
1484
    >>> os.environ["XDG_DATA_HOME"] = ""
 
1485
    >>> os.environ["XDG_DATA_DIRS"] = "/usr/share/gnome:/usr/local/share/:/usr/share/"
 
1486
    >>> XDGDirs.get_all_data_dirs("onboard/test.dat")
 
1487
    ['/home/test_user/.local/share/onboard/test.dat', \
 
1488
'/usr/share/gnome/onboard/test.dat', \
 
1489
'/usr/local/share/onboard/test.dat', \
 
1490
'/usr/share/onboard/test.dat']
 
1491
    """
 
1492
 
 
1493
    @staticmethod
 
1494
    def get_config_home(file = None):
 
1495
        """
 
1496
        User specific config directory.
 
1497
        """
 
1498
        path = os.environ.get("XDG_CONFIG_HOME")
 
1499
        if path and not os.path.isabs(path):
 
1500
            _logger.warning("XDG_CONFIG_HOME doesn't contain an absolute path,"
 
1501
                            "ignoring.")
 
1502
            path = None
 
1503
        if not path:
 
1504
            path = os.path.join(os.path.expanduser("~"), ".config")
 
1505
 
 
1506
        if file:
 
1507
            path = os.path.join(path, file)
 
1508
 
 
1509
        return path
 
1510
 
 
1511
    @staticmethod
 
1512
    def get_config_dirs():
 
1513
        """
 
1514
        Config directories ordered by preference.
 
1515
        """
 
1516
        paths = []
 
1517
 
 
1518
        value = os.environ.get("XDG_CONFIG_DIRS")
 
1519
        if not value:
 
1520
            value = "/etc/xdg"
 
1521
        
 
1522
        paths = value.split(":")
 
1523
        paths = [p for p in paths if os.path.isabs(p)]
 
1524
 
 
1525
        return paths
 
1526
 
 
1527
    @staticmethod
 
1528
    def get_all_config_dirs(file = None):
 
1529
        paths = [XDGDirs.get_config_home()] + XDGDirs.get_config_dirs()
 
1530
 
 
1531
        if file:
 
1532
            paths = [os.path.join(p, file) for p in paths]
 
1533
 
 
1534
        return paths
 
1535
 
 
1536
    @staticmethod
 
1537
    def find_config_files(file):
 
1538
        """ Find file in all config directories, highest priority first. """
 
1539
        paths = XDGDirs.get_all_config_dirs(file)
 
1540
        return [p for p in paths if os.path.isfile(path) and \
 
1541
                                    os.access(filename, os.R_OK)]
 
1542
 
 
1543
    @staticmethod
 
1544
    def find_config_file(file):
 
1545
        """ Find file of highest priority """
 
1546
        paths = XDGDirs.find_config_files(file)
 
1547
        if paths:
 
1548
            return paths[0]
 
1549
        return None
 
1550
 
 
1551
    @staticmethod
 
1552
    def get_data_home(file = None):
 
1553
        """
 
1554
        User specific data directory.
 
1555
        """
 
1556
        path = os.environ.get("XDG_DATA_HOME")
 
1557
        if path and not os.path.isabs(path):
 
1558
            _logger.warning("XDG_DATA_HOME doesn't contain an absolute path,"
 
1559
                            "ignoring.")
 
1560
            path = None
 
1561
        if not path:
 
1562
            path = os.path.join(os.path.expanduser("~"), ".local", "share")
 
1563
 
 
1564
        if file:
 
1565
            path = os.path.join(path, file)
 
1566
 
 
1567
        return path
 
1568
 
 
1569
    @staticmethod
 
1570
    def get_data_dirs():
 
1571
        """
 
1572
        Data directories ordered by preference.
 
1573
        """
 
1574
        paths = []
 
1575
 
 
1576
        value = os.environ.get("XDG_DATA_DIRS")
 
1577
        if not value:
 
1578
            value = "/usr/local/share/:/usr/share/"
 
1579
        
 
1580
        paths = value.split(":")
 
1581
        paths = [p for p in paths if os.path.isabs(p)]
 
1582
 
 
1583
        return paths
 
1584
 
 
1585
    @staticmethod
 
1586
    def get_all_data_dirs(file = None):
 
1587
        paths = [XDGDirs.get_data_home()] + XDGDirs.get_data_dirs()
 
1588
 
 
1589
        if file:
 
1590
            paths = [os.path.join(p, file) for p in paths]
 
1591
 
 
1592
        return paths
 
1593
 
 
1594
    @staticmethod
 
1595
    def find_data_files(file):
 
1596
        """ Find file in all data directories, highest priority first. """
 
1597
        paths = XDGDirs.get_all_data_dirs(file)
 
1598
        return [p for p in paths if os.path.isfile(path) and \
 
1599
                                    os.access(filename, os.R_OK)]
 
1600
 
 
1601
    @staticmethod
 
1602
    def find_data_file(file):
 
1603
        """ Find file of highest priority """
 
1604
        paths = XDGDirs.find_data_files(file)
 
1605
        if paths:
 
1606
            return paths[0]
 
1607
        return None
 
1608
 
 
1609
    def assure_user_dir_exists(path):
 
1610
        """
 
1611
        If necessary create user XDG directory.
 
1612
        Raises OSError.
 
1613
        """
 
1614
        exists = os.path.exists(path)
 
1615
        if not exists:
 
1616
            try:
 
1617
                os.makedirs(path, mode = 0o700)
 
1618
                exists = True
 
1619
            except OSError as ex:
 
1620
                _logger.error(_format("failed to create directory '{}': {}",
 
1621
                                       path, unicode_str(ex)))
 
1622
                raise ex
 
1623
        return exists
 
1624
 
 
1625