Changeset 246

Show
Ignore:
Timestamp:
2003-06-09 15:52:02 (6 years ago)
Author:
schwa
Message:
Moved line parsers from `ftputil.py` to `ftp_stat.py`. These parsers go
    into two classes, `_UnixStatParser` and `_MSStatParser`.
Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/ftp_stat.py

    r244 r246  
    3434""" 
    3535 
    36 # $Id: ftp_stat.py,v 1.3 2003/06/09 12:47:29 schwa Exp $ 
    37  
     36# $Id: ftp_stat.py,v 1.4 2003/06/09 15:52:02 schwa Exp $ 
     37 
     38import stat 
    3839import sys 
     40import time 
     41 
     42import ftp_error 
    3943 
    4044 
     
    8791        return stat_results 
    8892 
     93 
     94class _UnixStatParser(_StatParser): 
     95    # map month abbreviations to month numbers 
     96    _month_numbers = { 
     97      'jan':  1, 'feb':  2, 'mar':  3, 'apr':  4, 
     98      'may':  5, 'jun':  6, 'jul':  7, 'aug':  8, 
     99      'sep':  9, 'oct': 10, 'nov': 11, 'dec': 12} 
     100 
     101    def parse_line(self, line): 
     102        """ 
     103        Return `_Stat` instance corresponding to the given text line. 
     104        If the line can't be parsed, raise a `ParserError`. 
     105        """ 
     106        metadata, nlink, user, group, size, month, day, \ 
     107          year_or_time, name = line.split(None, 8) 
     108        # st_mode 
     109        st_mode = 0 
     110        for bit in metadata[1:10]: 
     111            bit = (bit != '-') 
     112            st_mode = (st_mode << 1) + bit 
     113        if metadata[3] == 's': 
     114            st_mode = st_mode | stat.S_ISUID 
     115        if metadata[6] == 's': 
     116            st_mode = st_mode | stat.S_ISGID 
     117        char_to_mode = {'d': stat.S_IFDIR, 'l': stat.S_IFLNK, 
     118                        'c': stat.S_IFCHR, '-': stat.S_IFREG} 
     119        file_type = metadata[0] 
     120        if char_to_mode.has_key(file_type): 
     121            st_mode = st_mode | char_to_mode[file_type] 
     122        else: 
     123            raise ftp_error.ParserError( 
     124                  "unknown file type character '%s'" % file_type) 
     125        # st_ino, st_dev, st_nlink, st_uid, st_gid, st_size, st_atime 
     126        st_ino = None 
     127        st_dev = None 
     128        st_nlink = int(nlink) 
     129        st_uid = user 
     130        st_gid = group 
     131        st_size = int(size) 
     132        st_atime = None 
     133        # st_mtime 
     134        month = self._month_numbers[ month.lower() ] 
     135        day = int(day) 
     136        if year_or_time.find(':') == -1: 
     137            # `year_or_time` is really a year 
     138            year, hour, minute = int(year_or_time), 0, 0 
     139            st_mtime = time.mktime( (year, month, day, hour, 
     140                       minute, 0, 0, 0, -1) ) 
     141        else: 
     142            # `year_or_time` is a time hh:mm 
     143            hour, minute = year_or_time.split(':') 
     144            year, hour, minute = None, int(hour), int(minute) 
     145            # try the current year 
     146            year = time.localtime()[0] 
     147            st_mtime = time.mktime( (year, month, day, hour, 
     148                       minute, 0, 0, 0, -1) ) 
     149            if st_mtime > time.time(): 
     150                # if it's in the future, use previous year 
     151                st_mtime = time.mktime( (year-1, month, day, 
     152                           hour, minute, 0, 0, 0, -1) ) 
     153        # st_ctime 
     154        st_ctime = None 
     155        # st_name 
     156        if name.find(' -> ') != -1: 
     157            st_name, st_target = name.split(' -> ') 
     158        else: 
     159            st_name, st_target = name, None 
     160        result = _Stat( (st_mode, st_ino, st_dev, st_nlink, st_uid, 
     161                         st_gid, st_size, st_atime, st_mtime, st_ctime) ) 
     162        result._st_name = st_name 
     163        result._st_target = st_target 
     164        return result 
     165 
     166 
     167class _MSStatParser(_StatParser): 
     168    def parse_line(self, line): 
     169        """ 
     170        Return `_Stat` instance corresponding to the given text line 
     171        from a MS ROBIN FTP server. If the line can't be parsed, 
     172        raise a `ParserError`. 
     173        """ 
     174        date, time_, dir_or_size, name = line.split(None, 3) 
     175        # st_mode 
     176        st_mode = 0400   # default to read access only; 
     177                         #  in fact, we can't tell 
     178        if dir_or_size == '<DIR>': 
     179            st_mode = st_mode | stat.S_IFDIR 
     180        else: 
     181            st_mode = st_mode | stat.S_IFREG 
     182        # st_ino, st_dev, st_nlink, st_uid, st_gid 
     183        st_ino = None 
     184        st_dev = None 
     185        st_nlink = None 
     186        st_uid = None 
     187        st_gid = None 
     188        # st_size 
     189        if dir_or_size != '<DIR>': 
     190            st_size = int(dir_or_size) 
     191        else: 
     192            st_size = None 
     193        # st_atime 
     194        st_atime = None 
     195        # st_mtime 
     196        month, day, year = map( int, date.split('-') ) 
     197        if year >= 70: 
     198            year = 1900 + year 
     199        else: 
     200            year = 2000 + year 
     201        hour, minute, am_pm = time_[0:2], time_[3:5], time_[5] 
     202        hour, minute = int(hour), int(minute) 
     203        if am_pm == 'P': 
     204            hour = 12 + hour 
     205        st_mtime = time.mktime( (year, month, day, hour, 
     206                   minute, 0, 0, 0, -1) ) 
     207        # st_ctime 
     208        st_ctime = None 
     209        result = _Stat( (st_mode, st_ino, st_dev, st_nlink, st_uid, 
     210                         st_gid, st_size, st_atime, st_mtime, st_ctime) ) 
     211        # _st_name and _st_target 
     212        result._st_name = name 
     213        result._st_target = None 
     214        return result 
    89215 
    90216 
  • trunk/ftputil.py

    r240 r246  
    3030# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
    3131 
    32 # $Id: ftputil.py,v 1.119 2003/06/08 19:47:13 schwa Exp $ 
     32# $Id: ftputil.py,v 1.120 2003/06/09 15:52:02 schwa Exp $ 
    3333 
    3434""" 
     
    170170        if response.find('ROBIN Microsoft') != -1 or \ 
    171171           response.find('Bliss_Server Microsoft') != -1: 
    172             self._parser = self._parse_ms_line 
     172            self._parser = ftp_stat._MSStatParser() 
    173173        else: 
    174             self._parser = self._parse_unix_line 
     174            self._parser = ftp_stat._UnixStatParser() 
    175175 
    176176    # 
     
    521521            if stat_result is not None: 
    522522                names.append(stat_result._st_name) 
    523         ftp_error._try_with_oserror(self._session.dir, path, callback
     523        ftp_error._try_with_oserror(self._session.dir, path, callback=callback
    524524        return names 
    525525 
     
    529529                 if line.find(wanted_name) != -1 ] 
    530530 
    531     _month_numbers = { 
    532       'jan':  1, 'feb':  2, 'mar':  3, 'apr':  4, 
    533       'may':  5, 'jun':  6, 'jul':  7, 'aug':  8, 
    534       'sep':  9, 'oct': 10, 'nov': 11, 'dec': 12} 
    535  
    536     def _parse_unix_line(self, line): 
    537         """ 
    538         Return `_Stat` instance corresponding to the given text line. 
    539         Exceptions are caught in `_parse_line`. 
    540         """ 
    541         metadata, nlink, user, group, size, month, day, \ 
    542           year_or_time, name = line.split(None, 8) 
    543         # st_mode 
    544         st_mode = 0 
    545         for bit in metadata[1:10]: 
    546             bit = (bit != '-') 
    547             st_mode = (st_mode << 1) + bit 
    548         if metadata[3] == 's': 
    549             st_mode = st_mode | stat.S_ISUID 
    550         if metadata[6] == 's': 
    551             st_mode = st_mode | stat.S_ISGID 
    552         char_to_mode = {'d': stat.S_IFDIR, 'l': stat.S_IFLNK, 
    553                         'c': stat.S_IFCHR, '-': stat.S_IFREG} 
    554         file_type = metadata[0] 
    555         if char_to_mode.has_key(file_type): 
    556             st_mode = st_mode | char_to_mode[file_type] 
    557         else: 
    558             raise ftp_error.ParserError( 
    559                   "unknown file type character '%s'" % file_type) 
    560         # st_ino, st_dev, st_nlink, st_uid, st_gid, st_size, st_atime 
    561         st_ino = None 
    562         st_dev = None 
    563         st_nlink = int(nlink) 
    564         st_uid = user 
    565         st_gid = group 
    566         st_size = int(size) 
    567         st_atime = None 
    568         # st_mtime 
    569         month = self._month_numbers[ month.lower() ] 
    570         day = int(day) 
    571         if year_or_time.find(':') == -1: 
    572             # `year_or_time` is really a year 
    573             year, hour, minute = int(year_or_time), 0, 0 
    574             st_mtime = time.mktime( (year, month, day, hour, 
    575                        minute, 0, 0, 0, -1) ) 
    576         else: 
    577             # `year_or_time` is a time hh:mm 
    578             hour, minute = year_or_time.split(':') 
    579             year, hour, minute = None, int(hour), int(minute) 
    580             # try the current year 
    581             year = time.localtime()[0] 
    582             st_mtime = time.mktime( (year, month, day, hour, 
    583                        minute, 0, 0, 0, -1) ) 
    584             if st_mtime > time.time(): 
    585                 # if it's in the future, use previous year 
    586                 st_mtime = time.mktime( (year-1, month, day, 
    587                            hour, minute, 0, 0, 0, -1) ) 
    588         # st_ctime 
    589         st_ctime = None 
    590         # st_name 
    591         if name.find(' -> ') != -1: 
    592             st_name, st_target = name.split(' -> ') 
    593         else: 
    594             st_name, st_target = name, None 
    595         result = ftp_stat._Stat( (st_mode, st_ino, st_dev, st_nlink, 
    596                                   st_uid, st_gid, st_size, st_atime, 
    597                                   st_mtime, st_ctime) ) 
    598         result._st_name = st_name 
    599         result._st_target = st_target 
    600         return result 
    601  
    602     def _parse_ms_line(self, line): 
    603         """ 
    604         Return `_Stat` instance corresponding to the given text line 
    605         from a MS ROBIN FTP server. Exceptions are caught in 
    606         `_parse_line`. 
    607         """ 
    608         date, time_, dir_or_size, name = line.split(None, 3) 
    609         # st_mode 
    610         st_mode = 0400   # default to read access only; 
    611                          #  in fact, we can't tell 
    612         if dir_or_size == '<DIR>': 
    613             st_mode = st_mode | stat.S_IFDIR 
    614         else: 
    615             st_mode = st_mode | stat.S_IFREG 
    616         # st_ino, st_dev, st_nlink, st_uid, st_gid 
    617         st_ino = None 
    618         st_dev = None 
    619         st_nlink = None 
    620         st_uid = None 
    621         st_gid = None 
    622         # st_size 
    623         if dir_or_size != '<DIR>': 
    624             st_size = int(dir_or_size) 
    625         else: 
    626             st_size = None 
    627         # st_atime 
    628         st_atime = None 
    629         # st_mtime 
    630         month, day, year = map( int, date.split('-') ) 
    631         if year >= 70: 
    632             year = 1900 + year 
    633         else: 
    634             year = 2000 + year 
    635         hour, minute, am_pm = time_[0:2], time_[3:5], time_[5] 
    636         hour, minute = int(hour), int(minute) 
    637         if am_pm == 'P': 
    638             hour = 12 + hour 
    639         st_mtime = time.mktime( (year, month, day, hour, 
    640                    minute, 0, 0, 0, -1) ) 
    641         # st_ctime 
    642         st_ctime = None 
    643         result = ftp_stat._Stat( (st_mode, st_ino, st_dev, st_nlink, 
    644                                   st_uid, st_gid, st_size, st_atime, 
    645                                   st_mtime, st_ctime) ) 
    646         # _st_name and _st_target 
    647         result._st_name = name 
    648         result._st_target = None 
    649         return result 
    650  
    651531    def _parse_line(self, line, fail=True): 
    652532        """Return `_Stat` instance corresponding to the given text line.""" 
    653533        try: 
    654             return self._parser(line) 
     534            return self._parser.parse_line(line) 
    655535        except (ValueError, IndexError): 
    656536            if fail: