Show More
@@ -689,6 +689,125 b' class observedbufferedinputpipe(buffered' | |||||
689 |
|
689 | |||
690 | return res |
|
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 | DATA_ESCAPE_MAP = {pycompat.bytechr(i): br'\x%02x' % i for i in range(256)} |
|
811 | DATA_ESCAPE_MAP = {pycompat.bytechr(i): br'\x%02x' % i for i in range(256)} | |
693 | DATA_ESCAPE_MAP.update({ |
|
812 | DATA_ESCAPE_MAP.update({ | |
694 | b'\\': b'\\\\', |
|
813 | b'\\': b'\\\\', | |
@@ -703,15 +822,7 b' def escapedata(s):' | |||||
703 |
|
822 | |||
704 | return DATA_ESCAPE_RE.sub(lambda m: DATA_ESCAPE_MAP[m.group(0)], s) |
|
823 | return DATA_ESCAPE_RE.sub(lambda m: DATA_ESCAPE_MAP[m.group(0)], s) | |
705 |
|
824 | |||
706 |
class |
|
825 | class baseproxyobserver(object): | |
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 |
|
||||
715 | def _writedata(self, data): |
|
826 | def _writedata(self, data): | |
716 | if not self.logdata: |
|
827 | if not self.logdata: | |
717 | self.fh.write('\n') |
|
828 | self.fh.write('\n') | |
@@ -731,6 +842,15 b' class fileobjectobserver(object):' | |||||
731 | self.fh.write('%s> %s\n' % (self.name, escapedata(line))) |
|
842 | self.fh.write('%s> %s\n' % (self.name, escapedata(line))) | |
732 | self.fh.flush() |
|
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 | def read(self, res, size=-1): |
|
854 | def read(self, res, size=-1): | |
735 | if not self.reads: |
|
855 | if not self.reads: | |
736 | return |
|
856 | return | |
@@ -793,6 +913,119 b' def makeloggingfileobject(logh, fh, name' | |||||
793 | logdata=logdata) |
|
913 | logdata=logdata) | |
794 | return fileobjectproxy(fh, observer) |
|
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 | def version(): |
|
1029 | def version(): | |
797 | """Return version information if available.""" |
|
1030 | """Return version information if available.""" | |
798 | try: |
|
1031 | try: |
General Comments 0
You need to be logged in to leave comments.
Login now