Show More
@@ -689,6 +689,125 b' class observedbufferedinputpipe(buffered' | |||
|
689 | 689 | |
|
690 | 690 | return res |
|
691 | 691 | |
|
692 | PROXIED_SOCKET_METHODS = { | |
|
693 | r'makefile', | |
|
694 | r'recv', | |
|
695 | r'recvfrom', | |
|
696 | r'recvfrom_into', | |
|
697 | r'recv_into', | |
|
698 | r'send', | |
|
699 | r'sendall', | |
|
700 | r'sendto', | |
|
701 | r'setblocking', | |
|
702 | r'settimeout', | |
|
703 | r'gettimeout', | |
|
704 | r'setsockopt', | |
|
705 | } | |
|
706 | ||
|
707 | class socketproxy(object): | |
|
708 | """A proxy around a socket that tells a watcher when events occur. | |
|
709 | ||
|
710 | This is like ``fileobjectproxy`` except for sockets. | |
|
711 | ||
|
712 | This type is intended to only be used for testing purposes. Think hard | |
|
713 | before using it in important code. | |
|
714 | """ | |
|
715 | __slots__ = ( | |
|
716 | r'_orig', | |
|
717 | r'_observer', | |
|
718 | ) | |
|
719 | ||
|
720 | def __init__(self, sock, observer): | |
|
721 | object.__setattr__(self, r'_orig', sock) | |
|
722 | object.__setattr__(self, r'_observer', observer) | |
|
723 | ||
|
724 | def __getattribute__(self, name): | |
|
725 | if name in PROXIED_SOCKET_METHODS: | |
|
726 | return object.__getattribute__(self, name) | |
|
727 | ||
|
728 | return getattr(object.__getattribute__(self, r'_orig'), name) | |
|
729 | ||
|
730 | def __delattr__(self, name): | |
|
731 | return delattr(object.__getattribute__(self, r'_orig'), name) | |
|
732 | ||
|
733 | def __setattr__(self, name, value): | |
|
734 | return setattr(object.__getattribute__(self, r'_orig'), name, value) | |
|
735 | ||
|
736 | def __nonzero__(self): | |
|
737 | return bool(object.__getattribute__(self, r'_orig')) | |
|
738 | ||
|
739 | __bool__ = __nonzero__ | |
|
740 | ||
|
741 | def _observedcall(self, name, *args, **kwargs): | |
|
742 | # Call the original object. | |
|
743 | orig = object.__getattribute__(self, r'_orig') | |
|
744 | res = getattr(orig, name)(*args, **kwargs) | |
|
745 | ||
|
746 | # Call a method on the observer of the same name with arguments | |
|
747 | # so it can react, log, etc. | |
|
748 | observer = object.__getattribute__(self, r'_observer') | |
|
749 | fn = getattr(observer, name, None) | |
|
750 | if fn: | |
|
751 | fn(res, *args, **kwargs) | |
|
752 | ||
|
753 | return res | |
|
754 | ||
|
755 | def makefile(self, *args, **kwargs): | |
|
756 | res = object.__getattribute__(self, r'_observedcall')( | |
|
757 | r'makefile', *args, **kwargs) | |
|
758 | ||
|
759 | # The file object may be used for I/O. So we turn it into a | |
|
760 | # proxy using our observer. | |
|
761 | observer = object.__getattribute__(self, r'_observer') | |
|
762 | return makeloggingfileobject(observer.fh, res, observer.name, | |
|
763 | reads=observer.reads, | |
|
764 | writes=observer.writes, | |
|
765 | logdata=observer.logdata) | |
|
766 | ||
|
767 | def recv(self, *args, **kwargs): | |
|
768 | return object.__getattribute__(self, r'_observedcall')( | |
|
769 | r'recv', *args, **kwargs) | |
|
770 | ||
|
771 | def recvfrom(self, *args, **kwargs): | |
|
772 | return object.__getattribute__(self, r'_observedcall')( | |
|
773 | r'recvfrom', *args, **kwargs) | |
|
774 | ||
|
775 | def recvfrom_into(self, *args, **kwargs): | |
|
776 | return object.__getattribute__(self, r'_observedcall')( | |
|
777 | r'recvfrom_into', *args, **kwargs) | |
|
778 | ||
|
779 | def recv_into(self, *args, **kwargs): | |
|
780 | return object.__getattribute__(self, r'_observedcall')( | |
|
781 | r'recv_info', *args, **kwargs) | |
|
782 | ||
|
783 | def send(self, *args, **kwargs): | |
|
784 | return object.__getattribute__(self, r'_observedcall')( | |
|
785 | r'send', *args, **kwargs) | |
|
786 | ||
|
787 | def sendall(self, *args, **kwargs): | |
|
788 | return object.__getattribute__(self, r'_observedcall')( | |
|
789 | r'sendall', *args, **kwargs) | |
|
790 | ||
|
791 | def sendto(self, *args, **kwargs): | |
|
792 | return object.__getattribute__(self, r'_observedcall')( | |
|
793 | r'sendto', *args, **kwargs) | |
|
794 | ||
|
795 | def setblocking(self, *args, **kwargs): | |
|
796 | return object.__getattribute__(self, r'_observedcall')( | |
|
797 | r'setblocking', *args, **kwargs) | |
|
798 | ||
|
799 | def settimeout(self, *args, **kwargs): | |
|
800 | return object.__getattribute__(self, r'_observedcall')( | |
|
801 | r'settimeout', *args, **kwargs) | |
|
802 | ||
|
803 | def gettimeout(self, *args, **kwargs): | |
|
804 | return object.__getattribute__(self, r'_observedcall')( | |
|
805 | r'gettimeout', *args, **kwargs) | |
|
806 | ||
|
807 | def setsockopt(self, *args, **kwargs): | |
|
808 | return object.__getattribute__(self, r'_observedcall')( | |
|
809 | r'setsockopt', *args, **kwargs) | |
|
810 | ||
|
692 | 811 | DATA_ESCAPE_MAP = {pycompat.bytechr(i): br'\x%02x' % i for i in range(256)} |
|
693 | 812 | DATA_ESCAPE_MAP.update({ |
|
694 | 813 | b'\\': b'\\\\', |
@@ -703,15 +822,7 b' def escapedata(s):' | |||
|
703 | 822 | |
|
704 | 823 | return DATA_ESCAPE_RE.sub(lambda m: DATA_ESCAPE_MAP[m.group(0)], s) |
|
705 | 824 | |
|
706 |
class |
|
|
707 | """Logs file object activity.""" | |
|
708 | def __init__(self, fh, name, reads=True, writes=True, logdata=False): | |
|
709 | self.fh = fh | |
|
710 | self.name = name | |
|
711 | self.logdata = logdata | |
|
712 | self.reads = reads | |
|
713 | self.writes = writes | |
|
714 | ||
|
825 | class baseproxyobserver(object): | |
|
715 | 826 | def _writedata(self, data): |
|
716 | 827 | if not self.logdata: |
|
717 | 828 | self.fh.write('\n') |
@@ -731,6 +842,15 b' class fileobjectobserver(object):' | |||
|
731 | 842 | self.fh.write('%s> %s\n' % (self.name, escapedata(line))) |
|
732 | 843 | self.fh.flush() |
|
733 | 844 | |
|
845 | class fileobjectobserver(baseproxyobserver): | |
|
846 | """Logs file object activity.""" | |
|
847 | def __init__(self, fh, name, reads=True, writes=True, logdata=False): | |
|
848 | self.fh = fh | |
|
849 | self.name = name | |
|
850 | self.logdata = logdata | |
|
851 | self.reads = reads | |
|
852 | self.writes = writes | |
|
853 | ||
|
734 | 854 | def read(self, res, size=-1): |
|
735 | 855 | if not self.reads: |
|
736 | 856 | return |
@@ -793,6 +913,119 b' def makeloggingfileobject(logh, fh, name' | |||
|
793 | 913 | logdata=logdata) |
|
794 | 914 | return fileobjectproxy(fh, observer) |
|
795 | 915 | |
|
916 | class socketobserver(baseproxyobserver): | |
|
917 | """Logs socket activity.""" | |
|
918 | def __init__(self, fh, name, reads=True, writes=True, states=True, | |
|
919 | logdata=False): | |
|
920 | self.fh = fh | |
|
921 | self.name = name | |
|
922 | self.reads = reads | |
|
923 | self.writes = writes | |
|
924 | self.states = states | |
|
925 | self.logdata = logdata | |
|
926 | ||
|
927 | def makefile(self, res, mode=None, bufsize=None): | |
|
928 | if not self.states: | |
|
929 | return | |
|
930 | ||
|
931 | self.fh.write('%s> makefile(%r, %r)\n' % ( | |
|
932 | self.name, mode, bufsize)) | |
|
933 | ||
|
934 | def recv(self, res, size, flags=0): | |
|
935 | if not self.reads: | |
|
936 | return | |
|
937 | ||
|
938 | self.fh.write('%s> recv(%d, %d) -> %d' % ( | |
|
939 | self.name, size, flags, len(res))) | |
|
940 | self._writedata(res) | |
|
941 | ||
|
942 | def recvfrom(self, res, size, flags=0): | |
|
943 | if not self.reads: | |
|
944 | return | |
|
945 | ||
|
946 | self.fh.write('%s> recvfrom(%d, %d) -> %d' % ( | |
|
947 | self.name, size, flags, len(res[0]))) | |
|
948 | self._writedata(res[0]) | |
|
949 | ||
|
950 | def recvfrom_into(self, res, buf, size, flags=0): | |
|
951 | if not self.reads: | |
|
952 | return | |
|
953 | ||
|
954 | self.fh.write('%s> recvfrom_into(%d, %d) -> %d' % ( | |
|
955 | self.name, size, flags, res[0])) | |
|
956 | self._writedata(buf[0:res[0]]) | |
|
957 | ||
|
958 | def recv_into(self, res, buf, size=0, flags=0): | |
|
959 | if not self.reads: | |
|
960 | return | |
|
961 | ||
|
962 | self.fh.write('%s> recv_into(%d, %d) -> %d' % ( | |
|
963 | self.name, size, flags, res)) | |
|
964 | self._writedata(buf[0:res]) | |
|
965 | ||
|
966 | def send(self, res, data, flags=0): | |
|
967 | if not self.writes: | |
|
968 | return | |
|
969 | ||
|
970 | self.fh.write('%s> send(%d, %d) -> %d' % ( | |
|
971 | self.name, len(data), flags, len(res))) | |
|
972 | self._writedata(data) | |
|
973 | ||
|
974 | def sendall(self, res, data, flags=0): | |
|
975 | if not self.writes: | |
|
976 | return | |
|
977 | ||
|
978 | # Returns None on success. So don't bother reporting return value. | |
|
979 | self.fh.write('%s> sendall(%d, %d)' % ( | |
|
980 | self.name, len(data), flags)) | |
|
981 | self._writedata(data) | |
|
982 | ||
|
983 | def sendto(self, res, data, flagsoraddress, address=None): | |
|
984 | if not self.writes: | |
|
985 | return | |
|
986 | ||
|
987 | if address: | |
|
988 | flags = flagsoraddress | |
|
989 | else: | |
|
990 | flags = 0 | |
|
991 | ||
|
992 | self.fh.write('%s> sendto(%d, %d, %r) -> %d' % ( | |
|
993 | self.name, len(data), flags, address, res)) | |
|
994 | self._writedata(data) | |
|
995 | ||
|
996 | def setblocking(self, res, flag): | |
|
997 | if not self.states: | |
|
998 | return | |
|
999 | ||
|
1000 | self.fh.write('%s> setblocking(%r)\n' % (self.name, flag)) | |
|
1001 | ||
|
1002 | def settimeout(self, res, value): | |
|
1003 | if not self.states: | |
|
1004 | return | |
|
1005 | ||
|
1006 | self.fh.write('%s> settimeout(%r)\n' % (self.name, value)) | |
|
1007 | ||
|
1008 | def gettimeout(self, res): | |
|
1009 | if not self.states: | |
|
1010 | return | |
|
1011 | ||
|
1012 | self.fh.write('%s> gettimeout() -> %f\n' % (self.name, res)) | |
|
1013 | ||
|
1014 | def setsockopt(self, level, optname, value): | |
|
1015 | if not self.states: | |
|
1016 | return | |
|
1017 | ||
|
1018 | self.fh.write('%s> setsockopt(%r, %r, %r) -> %r\n' % ( | |
|
1019 | self.name, level, optname, value)) | |
|
1020 | ||
|
1021 | def makeloggingsocket(logh, fh, name, reads=True, writes=True, states=True, | |
|
1022 | logdata=False): | |
|
1023 | """Turn a socket into a logging socket.""" | |
|
1024 | ||
|
1025 | observer = socketobserver(logh, name, reads=reads, writes=writes, | |
|
1026 | states=states, logdata=logdata) | |
|
1027 | return socketproxy(fh, observer) | |
|
1028 | ||
|
796 | 1029 | def version(): |
|
797 | 1030 | """Return version information if available.""" |
|
798 | 1031 | try: |
General Comments 0
You need to be logged in to leave comments.
Login now