1# Copyright 2013 The Chromium Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5"""A Resource is a file and its various associated canonical names."""
6
7import codecs
8import os
9
10
11class Resource(object):
12  """Represents a file found via a path search."""
13
14  def __init__(self, toplevel_dir, absolute_path, binary=False):
15    self.toplevel_dir = toplevel_dir
16    self.absolute_path = absolute_path
17    self._contents = None
18    self._binary = binary
19
20  @property
21  def relative_path(self):
22    """The path to the file from the top-level directory"""
23    return os.path.relpath(self.absolute_path, self.toplevel_dir)
24
25  @property
26  def unix_style_relative_path(self):
27    return self.relative_path.replace(os.sep, '/')
28
29  @property
30  def name(self):
31    """The dotted name for this resource based on its relative path."""
32    return self.name_from_relative_path(self.relative_path)
33
34  @staticmethod
35  def name_from_relative_path(relative_path):
36    dirname = os.path.dirname(relative_path)
37    basename = os.path.basename(relative_path)
38    modname = os.path.splitext(basename)[0]
39    if len(dirname):
40      name = dirname.replace(os.path.sep, '.') + '.' + modname
41    else:
42      name = modname
43    return name
44
45  @property
46  def contents(self):
47    if self._contents:
48      return self._contents
49    if not os.path.exists(self.absolute_path):
50      raise Exception('%s not found.' % self.absolute_path)
51    if self._binary:
52      f = open(self.absolute_path, mode='rb')
53    else:
54      f = codecs.open(self.absolute_path, mode='r', encoding='utf-8')
55    self._contents = f.read()
56    f.close()
57    return self._contents
58