Package pyctags :: Module tag_entry
[hide private]
[frames] | no frames]

Source Code for Module pyctags.tag_entry

  1  ## Copyright (C) 2008 Ben Smith <benjamin.coder.smith@gmail.com> 
  2   
  3  ##    This file is part of pyctags. 
  4   
  5  ##    pyctags is free software: you can redistribute it and/or modify 
  6  ##    it under the terms of the GNU Lesser General Public License as published 
  7  ##    by the Free Software Foundation, either version 3 of the License, or 
  8  ##    (at your option) any later version. 
  9   
 10  ##    pyctags is distributed in the hope that it will be useful, 
 11  ##    but WITHOUT ANY WARRANTY; without even the implied warranty of 
 12  ##    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 13  ##    GNU General Public License for more details. 
 14   
 15  ##    You should have received a copy of the GNU Lesser General Public License 
 16  ##    and the GNU Lesser General Public Licens along with pyctags.  If not,  
 17  ##    see <http://www.gnu.org/licenses/>. 
 18   
 19  """ 
 20  Python representation of ctags data elements. 
 21   
 22  This module uses the eval function, which will let package users execute arbitrary python code, if they want. 
 23  """ 
 24   
 25  from copy import copy 
 26  import os 
 27  try: 
 28      # do relative imports for tests 
 29      # try this first in case pyctags is already installed, since we want to be testing the source bundled in the distribution 
 30      from kwargs_validator import the_validator as validator 
 31  except ImportError: 
 32      from pyctags.kwargs_validator import the_validator as validator 
 33   
 34  _PYTHON_3000_ = True 
 35   
 36  import sys 
 37  if sys.version_info[0] < 3: 
 38      _PYTHON_3000_ = False 
 39       
 40  _COMMENT_BEGIN_ = ';"' 
 41   
42 -class ctags_entry:
43 """ 44 An entry in the tag file. 45 """
46 - def __init__(self, *args, **kwargs):
47 """ 48 A tag entry from ctags file. Initializes from str or keyword args. 49 - B{Optional Parameters:} 50 - B{args[0]}: (str) a ctags_entry repr or string from a tag file 51 - B{Keyword Arguments:} 52 - B{name}: (str) tag name 53 - B{file}: (str) source file name 54 - B{pattern}: (str) locator pattern for tag 55 - B{line_number}: (int) locator line number 56 - B{extensions}: (dict) extension fields 57 - B{Raises:} 58 - B{ValueError}: line_number or pattern isn't set, or a parameter type can't be transformed. 59 """ 60 valid_kwargs = ['name', 'file', 'pattern', 'line_number', 'extensions'] 61 validator.validate(kwargs.keys(), valid_kwargs) 62 63 self.name = None 64 """ Tag name.""" 65 self.file = None 66 """ Source file of tag.""" 67 self.pattern = None 68 """ If not None, regular expression to locate this tag in self.file.""" 69 self.line_number = None 70 """ If not None, line number to locate this tag in self.file.""" 71 self.extensions = None 72 """ If not none, dict of extension fields embedded in comments in the tag entry, from exuberant ctags.""" 73 self.__rep = None 74 75 entry = dict() 76 if len(args) == 1: 77 if len(kwargs): 78 raise ValueError("multiple tag data found in init") 79 80 if type(args[0]) == dict: 81 entry = args[0] 82 83 elif (type(args[0]) == str or type(args[0]) == unicode) and len(args[0]): 84 if args[0][0] == '{' and args[0][-1] == '}': 85 # expect this to be a repr string 86 # security anyone? 87 entry = eval(args[0]) 88 89 else: 90 argstr = args[0].strip() 91 # bah! uglies. 92 if not _PYTHON_3000_ and type(argstr) is not unicode: 93 argstr = unicode(argstr, "utf-8") 94 95 # this should be a tag line, could use some safety checking here though 96 (entry['name'], entry['file'], the_rest) = argstr.split('\t', 2) 97 98 extension_fields = None 99 100 if the_rest.find(_COMMENT_BEGIN_) > 0: 101 (locator, junk, extension_fields) = the_rest.rpartition(_COMMENT_BEGIN_) 102 else: 103 locator = the_rest 104 105 if locator.isdigit(): 106 try: 107 entry['line_number'] = int(locator) 108 except ValueError: 109 raise ValueError("Line number locator found for tag, but can't be converted to integer") 110 else: 111 # should be a regex pattern 112 entry['pattern'] = locator 113 114 entry['extensions'] = {} 115 kind_arg_found = False 116 if extension_fields: 117 if extension_fields[0] == '\t': 118 119 # probably exuberant ctags format 120 extension_list = extension_fields[1:].split('\t') 121 for ext in extension_list: 122 if ':' in ext: 123 (k, v) = ext.split(':', 1) 124 entry['extensions'][k] = v 125 if k == 'line' and 'line_number' not in entry: 126 try: 127 entry['line_number'] = int(v) 128 except ValueError: 129 raise ValueError("Extended tag 'line' found but can't be converted to integer.") 130 else: 131 if kind_arg_found: 132 raise ValueError("Unknown extended tag found.") 133 else: 134 entry['extensions']['kind'] = ext 135 kind_arg_found = True 136 137 elif len(kwargs): 138 entry = kwargs 139 140 if 'file' in entry: 141 self.file = entry['file'] 142 else: 143 raise ValueError("'file' parameter is required") 144 145 if 'name' in entry: 146 self.name = entry['name'] 147 else: 148 raise ValueError("'name' parameter is required") 149 150 if 'pattern' in entry: 151 self.pattern = entry['pattern'] 152 153 if 'line_number' in entry: 154 self.line_number = int(entry['line_number']) 155 156 if not self.line_number and not self.pattern: 157 raise ValueError("No valid locator for this tag.") 158 159 if 'extensions' in entry: 160 self.extensions = entry['extensions'] 161 162 163 self.__rep = entry
164
165 - def __repr__(self):
166 return str(self.__rep)
167
168 - def __str__(self):
169 idx = self.file.rfind('/') 170 171 if idx == -1: 172 idx = self.file.rfind("\\") 173 174 short_fn = self.file[idx + 1:] 175 176 if self.name: 177 return self.name + ':' + short_fn + ':' + str(self.line_number) 178 else: 179 return "Unnamed tag."
180
181 - def __eq__(self, other):
182 return (repr(self) == repr(other))
183
184 - def __ne__(self, other):
185 return (repr(self) != repr(other))
186