##// END OF EJS Templates
Walter's ipipe patch #8:...
vivainio -
Show More
@@ -157,6 +157,8 b' try:'
157 except ImportError:
157 except ImportError:
158 curses = None
158 curses = None
159
159
160 import path
161
160
162
161 __all__ = [
163 __all__ = [
162 "ifile", "ils", "iglob", "iwalk", "ipwdentry", "ipwd", "igrpentry", "igrp",
164 "ifile", "ils", "iglob", "iwalk", "ipwdentry", "ipwd", "igrpentry", "igrp",
@@ -342,7 +344,10 b' def _getattr(obj, name, default=_default):'
342 if name is None:
344 if name is None:
343 return obj
345 return obj
344 elif isinstance(name, basestring):
346 elif isinstance(name, basestring):
345 return getattr(obj, name, default)
347 if name.endswith("()"):
348 return getattr(obj, name[:-2], default)()
349 else:
350 return getattr(obj, name, default)
346 elif callable(name):
351 elif callable(name):
347 try:
352 try:
348 return name(obj)
353 return name(obj)
@@ -429,10 +434,12 b' style_default = Style(COLOR_WHITE, COLOR_BLACK)'
429 style_type_none = Style(COLOR_MAGENTA, COLOR_BLACK)
434 style_type_none = Style(COLOR_MAGENTA, COLOR_BLACK)
430 style_type_bool = Style(COLOR_MAGENTA, COLOR_BLACK)
435 style_type_bool = Style(COLOR_MAGENTA, COLOR_BLACK)
431 style_type_number = Style(COLOR_YELLOW, COLOR_BLACK)
436 style_type_number = Style(COLOR_YELLOW, COLOR_BLACK)
432 style_type_datetime = Style(COLOR_CYAN, COLOR_BLACK)
437 style_type_datetime = Style(COLOR_MAGENTA, COLOR_BLACK)
433
438
434 # Style for URLs and filenames
439 # Style for URLs and file/directory names
435 style_url = Style(COLOR_GREEN, COLOR_BLACK)
440 style_url = Style(COLOR_GREEN, COLOR_BLACK)
441 style_dir = Style(COLOR_CYAN, COLOR_BLACK)
442 style_file = Style(COLOR_GREEN, COLOR_BLACK)
436
443
437 # Style for ellipsis (when an output has been shortened
444 # Style for ellipsis (when an output has been shortened
438 style_ellisis = Style(COLOR_RED, COLOR_BLACK)
445 style_ellisis = Style(COLOR_RED, COLOR_BLACK)
@@ -659,69 +666,119 b' class ichain(Pipe):'
659 (self.__class__.__module__, self.__class__.__name__, args)
666 (self.__class__.__module__, self.__class__.__name__, args)
660
667
661
668
662 class ifile(object):
669 class ifile(path.path):
663 """
670 """
664 file (or directory) object.
671 file (or directory) object.
665 """
672 """
666 __slots__ = ("name", "_abspath", "_realpath", "_stat", "_lstat")
667
668 def __init__(self, name):
669 if isinstance(name, ifile): # copying files
670 self.name = name.name
671 self._abspath = name._abspath
672 self._realpath = name._realpath
673 self._stat = name._stat
674 self._lstat = name._lstat
675 else:
676 self.name = os.path.normpath(name)
677 self._abspath = None
678 self._realpath = None
679 self._stat = None
680 self._lstat = None
681
673
682 def __repr__(self):
674 def __add_(self, other):
683 return "%s.%s(%r)" % \
675 return ifile(path._base(self) + other)
684 (self.__class__.__module__, self.__class__.__name__, self.name)
685
676
686 def open(self, mode="rb", buffer=None):
677 def __radd_(self, other):
687 if buffer is None:
678 return ifile(other + path._base(self))
688 return open(self.abspath, mode)
679
689 else:
680 def __div_(self, other):
690 return open(self.abspath, mode, buffer)
681 return ifile(path.__div__(self, other))
691
682
692 def remove(self):
683 def getcwd():
693 os.remove(self.abspath)
684 """ Return the current working directory as a path object. """
694
685 return ifile(path.path.getcwd())
695 def getabspath(self):
686 getcwd = staticmethod(getcwd)
696 if self._abspath is None:
687
697 self._abspath = os.path.abspath(self.name)
688 def abspath(self):
698 return self._abspath
689 return ifile(path.path.abspath(self))
699 abspath = property(getabspath, None, None, "Path to file")
690
700
691 def normcase(self):
701 def getrealpath(self):
692 return ifile(path.path.normcase(self))
702 if self._realpath is None:
693
703 self._realpath = os.path.realpath(self.name)
694 def normpath(self):
704 return self._realpath
695 return ifile(path.path.normpath(self))
705 realpath = property(getrealpath, None, None, "Path with links resolved")
696
706
697 def realpath(self):
707 def getbasename(self):
698 return ifile(path.path.realpath(self))
708 return os.path.basename(self.abspath)
699
709 basename = property(getbasename, None, None, "File name without directory")
700 def expanduser(self):
710
701 return ifile(path.path.expanduser(self))
711 def getstat(self):
702
712 if self._stat is None:
703 def expandvars(self):
713 self._stat = os.stat(self.abspath)
704 return ifile(path.path.expandvars(self))
714 return self._stat
705
715 stat = property(getstat, None, None, "os.stat() result")
706 def dirname(self):
716
707 return ifile(path.path.dirname(self))
717 def getlstat(self):
708
718 if self._lstat is None:
709 parent = property(dirname, None, None, path.path.parent.__doc__)
719 self._lstat = os.lstat(self.abspath)
710
720 return self._lstat
711 def splitpath(self):
721 lstat = property(getlstat, None, None, "os.lstat() result")
712 (parent, child) = path.path.splitpath(self)
713 return (ifile(parent), child)
714
715 def splitdrive(self):
716 (drive, rel) = path.path.splitdrive(self)
717 return (ifile(drive), rel)
718
719 def splitext(self):
720 (filename, ext) = path.path.splitext(self)
721 return (ifile(filename), ext)
722
723 if hasattr(path.path, "splitunc"):
724 def splitunc(self):
725 (unc, rest) = path.path.splitunc(self)
726 return (ifile(unc), rest)
727
728 def _get_uncshare(self):
729 unc, r = os.path.splitunc(self)
730 return ifile(unc)
731
732 uncshare = property(
733 _get_uncshare, None, None,
734 """ The UNC mount point for this path.
735 This is empty for paths on local drives. """)
736
737 def joinpath(self, *args):
738 return ifile(path.path.joinpath(self, *args))
739
740 def splitall(self):
741 return map(ifile, path.path.splitall(self))
742
743 def relpath(self):
744 return ifile(path.path.relpath(self))
745
746 def relpathto(self, dest):
747 return ifile(path.path.relpathto(self, dest))
748
749 def listdir(self, pattern=None):
750 return [ifile(child) for child in path.path.listdir(self, pattern)]
751
752 def dirs(self, pattern=None):
753 return [ifile(child) for child in path.path.dirs(self, pattern)]
754
755 def files(self, pattern=None):
756 return [ifile(child) for child in path.path.files(self, pattern)]
757
758 def walk(self, pattern=None):
759 for child in path.path.walk(self, pattern):
760 yield ifile(child)
761
762 def walkdirs(self, pattern=None):
763 for child in path.path.walkdirs(self, pattern):
764 yield ifile(child)
765
766 def walkfiles(self, pattern=None):
767 for child in path.path.walkfiles(self, pattern):
768 yield ifile(child)
769
770 def glob(self, pattern):
771 return map(ifile, path.path.glob(self, pattern))
772
773 if hasattr(os, 'readlink'):
774 def readlink(self):
775 return ifile(path.path.readlink(self))
776
777 def readlinkabs(self):
778 return ifile(path.path.readlinkabs(self))
722
779
723 def getmode(self):
780 def getmode(self):
724 return self.stat.st_mode
781 return self.stat().st_mode
725 mode = property(getmode, None, None, "Access mode")
782 mode = property(getmode, None, None, "Access mode")
726
783
727 def gettype(self):
784 def gettype(self):
@@ -734,7 +791,7 b' class ifile(object):'
734 (stat.S_ISLNK, "symlink"),
791 (stat.S_ISLNK, "symlink"),
735 (stat.S_ISSOCK,"socket"),
792 (stat.S_ISSOCK,"socket"),
736 ]
793 ]
737 lstat = self.lstat
794 lstat = self.lstat()
738 if lstat is not None:
795 if lstat is not None:
739 types = set([text for (func, text) in data if func(lstat.st_mode)])
796 types = set([text for (func, text) in data if func(lstat.st_mode)])
740 else:
797 else:
@@ -742,9 +799,9 b' class ifile(object):'
742 m = self.mode
799 m = self.mode
743 types.update([text for (func, text) in data if func(m)])
800 types.update([text for (func, text) in data if func(m)])
744 return ", ".join(types)
801 return ", ".join(types)
745 type = property(gettype, None, None, "file type")
802 type = property(gettype, None, None, "file type (file, directory, link, etc.)")
746
803
747 def getaccess(self):
804 def getmodestr(self):
748 m = self.mode
805 m = self.mode
749 data = [
806 data = [
750 (stat.S_IRUSR, "-r"),
807 (stat.S_IRUSR, "-r"),
@@ -759,164 +816,130 b' class ifile(object):'
759 ]
816 ]
760 return "".join([text[bool(m&bit)] for (bit, text) in data])
817 return "".join([text[bool(m&bit)] for (bit, text) in data])
761
818
762 access = property(getaccess, None, None, "Access mode as string")
819 modestr = property(getmodestr, None, None, "Access mode as string")
763
764 def getsize(self):
765 return int(self.stat.st_size)
766 size = property(getsize, None, None, "File size in bytes")
767
820
768 def getblocks(self):
821 def getblocks(self):
769 return self.stat.st_blocks
822 return self.stat().st_blocks
770 blocks = property(getblocks, None, None, "File size in blocks")
823 blocks = property(getblocks, None, None, "File size in blocks")
771
824
772 def getblksize(self):
825 def getblksize(self):
773 return self.stat.st_blksize
826 return self.stat().st_blksize
774 blksize = property(getblksize, None, None, "Filesystem block size")
827 blksize = property(getblksize, None, None, "Filesystem block size")
775
828
776 def getdev(self):
829 def getdev(self):
777 return self.stat.st_dev
830 return self.stat().st_dev
778 dev = property(getdev)
831 dev = property(getdev)
779
832
780 def getnlink(self):
833 def getnlink(self):
781 return self.stat.st_nlink
834 return self.stat().st_nlink
782 nlink = property(getnlink, None, None, "Number of links")
835 nlink = property(getnlink, None, None, "Number of links")
783
836
784 def getuid(self):
837 def getuid(self):
785 return self.stat.st_uid
838 return self.stat().st_uid
786 uid = property(getuid, None, None, "User id of file owner")
839 uid = property(getuid, None, None, "User id of file owner")
787
840
788 def getgid(self):
841 def getgid(self):
789 return self.stat.st_gid
842 return self.stat().st_gid
790 gid = property(getgid, None, None, "Group id of file owner")
843 gid = property(getgid, None, None, "Group id of file owner")
791
844
792 def getowner(self):
845 def getowner(self):
846 stat = self.stat()
793 try:
847 try:
794 return pwd.getpwuid(self.stat.st_uid).pw_name
848 return pwd.getpwuid(stat.st_uid).pw_name
795 except KeyError:
849 except KeyError:
796 return self.stat.st_uid
850 return stat.st_uid
797 owner = property(getowner, None, None, "Owner name (or id)")
851 owner = property(getowner, None, None, "Owner name (or id)")
798
852
799 def getgroup(self):
853 def getgroup(self):
854 stat = self.stat()
800 try:
855 try:
801 return grp.getgrgid(self.stat.st_gid).gr_name
856 return grp.getgrgid(stat.st_gid).gr_name
802 except KeyError:
857 except KeyError:
803 return self.stat.st_gid
858 return stat.st_gid
804 group = property(getgroup, None, None, "Group name (or id)")
859 group = property(getgroup, None, None, "Group name (or id)")
805
860
806 def getatime(self):
807 return self.stat.st_atime
808 atime = property(getatime, None, None, "Access date")
809
810 def getadate(self):
861 def getadate(self):
811 return datetime.datetime.utcfromtimestamp(self.atime)
862 return datetime.datetime.utcfromtimestamp(self.atime)
812 adate = property(getadate, None, None, "Access date")
863 adate = property(getadate, None, None, "Access date")
813
864
814 def getctime(self):
815 return self.stat.st_ctime
816 ctime = property(getctime, None, None, "Creation date")
817
818 def getcdate(self):
865 def getcdate(self):
819 return datetime.datetime.utcfromtimestamp(self.ctime)
866 return datetime.datetime.utcfromtimestamp(self.ctime)
820 cdate = property(getcdate, None, None, "Creation date")
867 cdate = property(getcdate, None, None, "Creation date")
821
868
822 def getmtime(self):
823 return self.stat.st_mtime
824 mtime = property(getmtime, None, None, "Modification date")
825
826 def getmdate(self):
869 def getmdate(self):
827 return datetime.datetime.utcfromtimestamp(self.mtime)
870 return datetime.datetime.utcfromtimestamp(self.mtime)
828 mdate = property(getmdate, None, None, "Modification date")
871 mdate = property(getmdate, None, None, "Modification date")
829
872
830 def getmimetype(self):
873 def getmimetype(self):
831 return mimetypes.guess_type(self.basename)[0]
874 return mimetypes.guess_type(self.basename())[0]
832 mimetype = property(getmimetype, None, None, "MIME type")
875 mimetype = property(getmimetype, None, None, "MIME type")
833
876
834 def getencoding(self):
877 def getencoding(self):
835 return mimetypes.guess_type(self.basename)[1]
878 return mimetypes.guess_type(self.basename())[1]
836 encoding = property(getencoding, None, None, "Compression")
879 encoding = property(getencoding, None, None, "Compression")
837
880
838 def getisdir(self):
881 def __repr__(self):
839 return os.path.isdir(self.abspath)
882 return "ifile(%s)" % path._base.__repr__(self)
840 isdir = property(getisdir, None, None, "Is this a directory?")
841
842 def getislink(self):
843 return os.path.islink(self.abspath)
844 islink = property(getislink, None, None, "Is this a link?")
845
846 def __eq__(self, other):
847 return self.abspath == other.abspath
848
883
849 def __neq__(self, other):
884 defaultattrs = (None, "type", "size", "modestr", "owner", "group", "mdate")
850 return self.abspath != other.abspath
851
885
852 def __xattrs__(self, mode):
886 def __xattrs__(self, mode):
853 if mode == "detail":
887 if mode == "detail":
854 return (
888 return (
855 "name", "basename", "abspath", "realpath",
889 "name", "basename()", "abspath()", "realpath()",
856 "mode", "type", "access", "stat", "lstat",
890 "type", "mode", "modestr", "stat()", "lstat()",
857 "uid", "gid", "owner", "group", "dev", "nlink",
891 "uid", "gid", "owner", "group", "dev", "nlink",
858 "ctime", "mtime", "atime", "cdate", "mdate", "adate",
892 "ctime", "mtime", "atime", "cdate", "mdate", "adate",
859 "size", "blocks", "blksize", "isdir", "islink",
893 "size", "blocks", "blksize", "isdir()", "islink()",
860 "mimetype", "encoding"
894 "mimetype", "encoding"
861 )
895 )
862 return ("name", "type", "size", "access", "owner", "group", "mdate")
896 return self.defaultattrs
863
897
864 def __xrepr__(self, mode):
898 def __xrepr__(self, mode):
865 yield (-1, True)
899 yield (-1, True)
866 if mode in "header" or mode == "footer" or mode == "cell":
900 try:
901 if self.isdir():
902 name = "idir"
903 style = style_dir
904 else:
905 name = "ifile"
906 style = style_file
907 except IOError:
867 name = "ifile"
908 name = "ifile"
868 try:
909 style = style_default
869 if self.isdir:
910 if mode == "cell" or mode in "header" or mode == "footer":
870 name = "idir"
911 abspath = repr(path._base(self.abspath()))
871 except IOError:
912 if abspath.startswith("u"):
872 pass
913 abspath = abspath[2:-1]
873 yield (style_url, "%s(%r)" % (name, self.abspath))
914 else:
874 elif mode == "cell":
915 abspath = abspath[1:-1]
875 yield (style_url, repr(self.abspath)[1:-1])
916 if mode == "cell":
917 yield (style, abspath)
918 else:
919 yield (style, "%s(%s)" % (name, abspath))
876 else:
920 else:
877 yield (style_url, repr(self))
921 yield (style, repr(self))
878
922
879 def __xiter__(self, mode):
923 def __xiter__(self, mode):
880 if self.isdir:
924 if self.isdir():
881 abspath = self.abspath
925 yield iparentdir(self / os.pardir)
882 if abspath != os.path.abspath(os.path.join(abspath, os.pardir)):
926 for child in sorted(self.listdir()):
883 yield iparentdir(abspath)
927 yield child
884 for name in sorted(os.listdir(abspath), key=lambda n: n.lower()):
885 if self.name != os.curdir:
886 name = os.path.join(abspath, name)
887 yield ifile(name)
888 else:
928 else:
889 f = self.open("rb")
929 f = self.open("rb")
890 for line in f:
930 for line in f:
891 yield line
931 yield line
892 f.close()
932 f.close()
893
933
894 def __repr__(self):
895 return "%s.%s(%r)" % \
896 (self.__class__.__module__, self.__class__.__name__, self.abspath)
897
898
934
899 class iparentdir(ifile):
935 class iparentdir(ifile):
900 def __init__(self, base):
936 def __xrepr__(self, mode):
901 self._base = base
937 yield (-1, True)
902 self.name = os.pardir
938 if mode == "cell":
903 self._abspath = None
939 yield (style_dir, os.pardir)
904 self._realpath = None
940 else:
905 self._stat = None
941 for part in ifile.__xrepr__(self, mode):
906 self._lstat = None
942 yield part
907
908 def getabspath(self):
909 if self._abspath is None:
910 self._abspath = os.path.abspath(os.path.join(self._base, self.name))
911 return self._abspath
912 abspath = property(getabspath, None, None, "Path to file")
913
914 def getrealpath(self):
915 if self._realpath is None:
916 self._realpath = os.path.realpath(
917 os.path.join(self._base, self.name))
918 return self._realpath
919 realpath = property(getrealpath, None, None, "Path with links resolved")
920
943
921
944
922 class ils(Table):
945 class ils(Table):
@@ -930,13 +953,7 b' class ils(Table):'
930 return xiter(ifile(self.base), mode)
953 return xiter(ifile(self.base), mode)
931
954
932 def __xrepr__(self, mode):
955 def __xrepr__(self, mode):
933 yield (-1, True)
956 return ifile(self.base).__xrepr__(mode)
934 if mode == "header" or mode == "footer" or mode == "cell":
935 yield (style_url, "idir(%r)" % (os.path.abspath(self.base)))
936 elif mode == "cell":
937 yield (style_url, repr(os.path.abspath(self.base))[1:-1])
938 else:
939 yield (style_url, repr(self))
940
957
941 def __repr__(self):
958 def __repr__(self):
942 return "%s.%s(%r)" % \
959 return "%s.%s(%r)" % \
@@ -1752,18 +1769,19 b' class XAttr(object):'
1752
1769
1753 doc = None
1770 doc = None
1754 if isinstance(name, basestring):
1771 if isinstance(name, basestring):
1755 try:
1772 if name.endswith("()"):
1756 meta = getattr(type(object), name)
1773 doc = getattr(getattr(object, name[:-2]), "__doc__", None)
1757 except AttributeError:
1758 pass
1759 else:
1774 else:
1760 if isinstance(meta, property):
1775 try:
1761 self.doc = getattr(meta, "__doc__", None)
1776 meta = getattr(type(object), name)
1777 except AttributeError:
1778 pass
1779 else:
1780 if isinstance(meta, property):
1781 doc = getattr(meta, "__doc__", None)
1762 elif callable(name):
1782 elif callable(name):
1763 try:
1783 doc = getattr(name, "__doc__", None)
1764 self.doc = name.__doc__
1784 self.doc = doc
1765 except AttributeError:
1766 pass
1767
1785
1768 def __xattrs__(self, mode):
1786 def __xattrs__(self, mode):
1769 return ("name", "type", "doc", "value")
1787 return ("name", "type", "doc", "value")
General Comments 0
You need to be logged in to leave comments. Login now