├── .gitignore ├── .site-packages ├── PIL │ ├── BdfFontFile.py │ ├── BlpImagePlugin.py │ ├── BmpImagePlugin.py │ ├── BufrStubImagePlugin.py │ ├── ContainerIO.py │ ├── CurImagePlugin.py │ ├── DcxImagePlugin.py │ ├── DdsImagePlugin.py │ ├── EpsImagePlugin.py │ ├── ExifTags.py │ ├── FitsImagePlugin.py │ ├── FitsStubImagePlugin.py │ ├── FliImagePlugin.py │ ├── FontFile.py │ ├── FpxImagePlugin.py │ ├── FtexImagePlugin.py │ ├── GbrImagePlugin.py │ ├── GdImageFile.py │ ├── GifImagePlugin.py │ ├── GimpGradientFile.py │ ├── GimpPaletteFile.py │ ├── GribStubImagePlugin.py │ ├── Hdf5StubImagePlugin.py │ ├── IcnsImagePlugin.py │ ├── IcoImagePlugin.py │ ├── ImImagePlugin.py │ ├── Image.py │ ├── ImageChops.py │ ├── ImageCms.py │ ├── ImageColor.py │ ├── ImageDraw.py │ ├── ImageDraw2.py │ ├── ImageEnhance.py │ ├── ImageFile.py │ ├── ImageFilter.py │ ├── ImageFont.py │ ├── ImageGrab.py │ ├── ImageMath.py │ ├── ImageMode.py │ ├── ImageMorph.py │ ├── ImageOps.py │ ├── ImagePalette.py │ ├── ImagePath.py │ ├── ImageQt.py │ ├── ImageSequence.py │ ├── ImageShow.py │ ├── ImageStat.py │ ├── ImageTk.py │ ├── ImageTransform.py │ ├── ImageWin.py │ ├── ImtImagePlugin.py │ ├── IptcImagePlugin.py │ ├── Jpeg2KImagePlugin.py │ ├── JpegImagePlugin.py │ ├── JpegPresets.py │ ├── McIdasImagePlugin.py │ ├── MicImagePlugin.py │ ├── MpegImagePlugin.py │ ├── MpoImagePlugin.py │ ├── MspImagePlugin.py │ ├── PSDraw.py │ ├── PaletteFile.py │ ├── PalmImagePlugin.py │ ├── PcdImagePlugin.py │ ├── PcfFontFile.py │ ├── PcxImagePlugin.py │ ├── PdfImagePlugin.py │ ├── PdfParser.py │ ├── PixarImagePlugin.py │ ├── PngImagePlugin.py │ ├── PpmImagePlugin.py │ ├── PsdImagePlugin.py │ ├── PyAccess.py │ ├── SgiImagePlugin.py │ ├── SpiderImagePlugin.py │ ├── SunImagePlugin.py │ ├── TarIO.py │ ├── TgaImagePlugin.py │ ├── TiffImagePlugin.py │ ├── TiffTags.py │ ├── WalImageFile.py │ ├── WebPImagePlugin.py │ ├── WmfImagePlugin.py │ ├── XVThumbImagePlugin.py │ ├── XbmImagePlugin.py │ ├── XpmImagePlugin.py │ ├── __init__.py │ ├── __main__.py │ ├── _binary.py │ ├── _tkinter_finder.py │ ├── _util.py │ ├── _version.py │ └── features.py ├── bin │ └── normalizer ├── certifi │ ├── __init__.py │ ├── __main__.py │ ├── cacert.pem │ └── core.py ├── charset_normalizer │ ├── __init__.py │ ├── api.py │ ├── assets │ │ └── __init__.py │ ├── cd.py │ ├── cli │ │ ├── __init__.py │ │ └── normalizer.py │ ├── constant.py │ ├── legacy.py │ ├── md.py │ ├── models.py │ ├── py.typed │ ├── utils.py │ └── version.py ├── idna │ ├── __init__.py │ ├── codec.py │ ├── compat.py │ ├── core.py │ ├── idnadata.py │ ├── intranges.py │ ├── package_data.py │ ├── py.typed │ └── uts46data.py ├── pyperclip │ ├── __init__.py │ └── __main__.py ├── requests │ ├── __init__.py │ ├── __version__.py │ ├── _internal_utils.py │ ├── adapters.py │ ├── api.py │ ├── auth.py │ ├── certs.py │ ├── compat.py │ ├── cookies.py │ ├── exceptions.py │ ├── help.py │ ├── hooks.py │ ├── models.py │ ├── packages.py │ ├── sessions.py │ ├── status_codes.py │ ├── structures.py │ └── utils.py ├── six.py ├── urllib3 │ ├── __init__.py │ ├── _collections.py │ ├── _version.py │ ├── connection.py │ ├── connectionpool.py │ ├── contrib │ │ ├── __init__.py │ │ ├── _appengine_environ.py │ │ ├── _securetransport │ │ │ ├── __init__.py │ │ │ ├── bindings.py │ │ │ └── low_level.py │ │ ├── appengine.py │ │ ├── ntlmpool.py │ │ ├── pyopenssl.py │ │ ├── securetransport.py │ │ └── socks.py │ ├── exceptions.py │ ├── fields.py │ ├── filepost.py │ ├── packages │ │ ├── __init__.py │ │ ├── backports │ │ │ ├── __init__.py │ │ │ └── makefile.py │ │ └── six.py │ ├── poolmanager.py │ ├── request.py │ ├── response.py │ └── util │ │ ├── __init__.py │ │ ├── connection.py │ │ ├── proxy.py │ │ ├── queue.py │ │ ├── request.py │ │ ├── response.py │ │ ├── retry.py │ │ ├── ssl_.py │ │ ├── ssl_match_hostname.py │ │ ├── ssltransport.py │ │ ├── timeout.py │ │ ├── url.py │ │ └── wait.py └── workflow │ ├── Notify.tgz │ ├── __init__.py │ ├── background.py │ ├── notify.py │ ├── update.py │ ├── util.py │ ├── version │ ├── workflow.py │ └── workflow3.py ├── 7D9DF57A-5DF9-5DB9-AB88-88DAC6AD7FB1.png ├── README.md ├── __version__.py ├── build-workflow-distributable.sh ├── entrypoint.py ├── icon.png ├── info.plist └── lib ├── biplist-1.0.3.dist-info ├── AUTHORS ├── INSTALLER ├── LICENSE ├── METADATA ├── RECORD ├── REQUESTED ├── WHEEL └── top_level.txt └── biplist └── __init__.py /.gitignore: -------------------------------------------------------------------------------- 1 | alfred-iterm-profiles-workflow.alfredworkflow 2 | -------------------------------------------------------------------------------- /.site-packages/PIL/BdfFontFile.py: -------------------------------------------------------------------------------- 1 | # 2 | # The Python Imaging Library 3 | # $Id$ 4 | # 5 | # bitmap distribution font (bdf) file parser 6 | # 7 | # history: 8 | # 1996-05-16 fl created (as bdf2pil) 9 | # 1997-08-25 fl converted to FontFile driver 10 | # 2001-05-25 fl removed bogus __init__ call 11 | # 2002-11-20 fl robustification (from Kevin Cazabon, Dmitry Vasiliev) 12 | # 2003-04-22 fl more robustification (from Graham Dumpleton) 13 | # 14 | # Copyright (c) 1997-2003 by Secret Labs AB. 15 | # Copyright (c) 1997-2003 by Fredrik Lundh. 16 | # 17 | # See the README file for information on usage and redistribution. 18 | # 19 | 20 | """ 21 | Parse X Bitmap Distribution Format (BDF) 22 | """ 23 | 24 | 25 | from . import FontFile, Image 26 | 27 | bdf_slant = { 28 | "R": "Roman", 29 | "I": "Italic", 30 | "O": "Oblique", 31 | "RI": "Reverse Italic", 32 | "RO": "Reverse Oblique", 33 | "OT": "Other", 34 | } 35 | 36 | bdf_spacing = {"P": "Proportional", "M": "Monospaced", "C": "Cell"} 37 | 38 | 39 | def bdf_char(f): 40 | # skip to STARTCHAR 41 | while True: 42 | s = f.readline() 43 | if not s: 44 | return None 45 | if s[:9] == b"STARTCHAR": 46 | break 47 | id = s[9:].strip().decode("ascii") 48 | 49 | # load symbol properties 50 | props = {} 51 | while True: 52 | s = f.readline() 53 | if not s or s[:6] == b"BITMAP": 54 | break 55 | i = s.find(b" ") 56 | props[s[:i].decode("ascii")] = s[i + 1 : -1].decode("ascii") 57 | 58 | # load bitmap 59 | bitmap = [] 60 | while True: 61 | s = f.readline() 62 | if not s or s[:7] == b"ENDCHAR": 63 | break 64 | bitmap.append(s[:-1]) 65 | bitmap = b"".join(bitmap) 66 | 67 | [x, y, l, d] = [int(p) for p in props["BBX"].split()] 68 | [dx, dy] = [int(p) for p in props["DWIDTH"].split()] 69 | 70 | bbox = (dx, dy), (l, -d - y, x + l, -d), (0, 0, x, y) 71 | 72 | try: 73 | im = Image.frombytes("1", (x, y), bitmap, "hex", "1") 74 | except ValueError: 75 | # deal with zero-width characters 76 | im = Image.new("1", (x, y)) 77 | 78 | return id, int(props["ENCODING"]), bbox, im 79 | 80 | 81 | class BdfFontFile(FontFile.FontFile): 82 | """Font file plugin for the X11 BDF format.""" 83 | 84 | def __init__(self, fp): 85 | super().__init__() 86 | 87 | s = fp.readline() 88 | if s[:13] != b"STARTFONT 2.1": 89 | raise SyntaxError("not a valid BDF file") 90 | 91 | props = {} 92 | comments = [] 93 | 94 | while True: 95 | s = fp.readline() 96 | if not s or s[:13] == b"ENDPROPERTIES": 97 | break 98 | i = s.find(b" ") 99 | props[s[:i].decode("ascii")] = s[i + 1 : -1].decode("ascii") 100 | if s[:i] in [b"COMMENT", b"COPYRIGHT"]: 101 | if s.find(b"LogicalFontDescription") < 0: 102 | comments.append(s[i + 1 : -1].decode("ascii")) 103 | 104 | while True: 105 | c = bdf_char(fp) 106 | if not c: 107 | break 108 | id, ch, (xy, dst, src), im = c 109 | if 0 <= ch < len(self.glyph): 110 | self.glyph[ch] = xy, dst, src, im 111 | -------------------------------------------------------------------------------- /.site-packages/PIL/BufrStubImagePlugin.py: -------------------------------------------------------------------------------- 1 | # 2 | # The Python Imaging Library 3 | # $Id$ 4 | # 5 | # BUFR stub adapter 6 | # 7 | # Copyright (c) 1996-2003 by Fredrik Lundh 8 | # 9 | # See the README file for information on usage and redistribution. 10 | # 11 | 12 | from . import Image, ImageFile 13 | 14 | _handler = None 15 | 16 | 17 | def register_handler(handler): 18 | """ 19 | Install application-specific BUFR image handler. 20 | 21 | :param handler: Handler object. 22 | """ 23 | global _handler 24 | _handler = handler 25 | 26 | 27 | # -------------------------------------------------------------------- 28 | # Image adapter 29 | 30 | 31 | def _accept(prefix): 32 | return prefix[:4] == b"BUFR" or prefix[:4] == b"ZCZC" 33 | 34 | 35 | class BufrStubImageFile(ImageFile.StubImageFile): 36 | 37 | format = "BUFR" 38 | format_description = "BUFR" 39 | 40 | def _open(self): 41 | 42 | offset = self.fp.tell() 43 | 44 | if not _accept(self.fp.read(4)): 45 | raise SyntaxError("Not a BUFR file") 46 | 47 | self.fp.seek(offset) 48 | 49 | # make something up 50 | self.mode = "F" 51 | self._size = 1, 1 52 | 53 | loader = self._load() 54 | if loader: 55 | loader.open(self) 56 | 57 | def _load(self): 58 | return _handler 59 | 60 | 61 | def _save(im, fp, filename): 62 | if _handler is None or not hasattr(_handler, "save"): 63 | raise OSError("BUFR save handler not installed") 64 | _handler.save(im, fp, filename) 65 | 66 | 67 | # -------------------------------------------------------------------- 68 | # Registry 69 | 70 | Image.register_open(BufrStubImageFile.format, BufrStubImageFile, _accept) 71 | Image.register_save(BufrStubImageFile.format, _save) 72 | 73 | Image.register_extension(BufrStubImageFile.format, ".bufr") 74 | -------------------------------------------------------------------------------- /.site-packages/PIL/ContainerIO.py: -------------------------------------------------------------------------------- 1 | # 2 | # The Python Imaging Library. 3 | # $Id$ 4 | # 5 | # a class to read from a container file 6 | # 7 | # History: 8 | # 1995-06-18 fl Created 9 | # 1995-09-07 fl Added readline(), readlines() 10 | # 11 | # Copyright (c) 1997-2001 by Secret Labs AB 12 | # Copyright (c) 1995 by Fredrik Lundh 13 | # 14 | # See the README file for information on usage and redistribution. 15 | # 16 | 17 | 18 | import io 19 | 20 | 21 | class ContainerIO: 22 | """ 23 | A file object that provides read access to a part of an existing 24 | file (for example a TAR file). 25 | """ 26 | 27 | def __init__(self, file, offset, length): 28 | """ 29 | Create file object. 30 | 31 | :param file: Existing file. 32 | :param offset: Start of region, in bytes. 33 | :param length: Size of region, in bytes. 34 | """ 35 | self.fh = file 36 | self.pos = 0 37 | self.offset = offset 38 | self.length = length 39 | self.fh.seek(offset) 40 | 41 | ## 42 | # Always false. 43 | 44 | def isatty(self): 45 | return False 46 | 47 | def seek(self, offset, mode=io.SEEK_SET): 48 | """ 49 | Move file pointer. 50 | 51 | :param offset: Offset in bytes. 52 | :param mode: Starting position. Use 0 for beginning of region, 1 53 | for current offset, and 2 for end of region. You cannot move 54 | the pointer outside the defined region. 55 | """ 56 | if mode == 1: 57 | self.pos = self.pos + offset 58 | elif mode == 2: 59 | self.pos = self.length + offset 60 | else: 61 | self.pos = offset 62 | # clamp 63 | self.pos = max(0, min(self.pos, self.length)) 64 | self.fh.seek(self.offset + self.pos) 65 | 66 | def tell(self): 67 | """ 68 | Get current file pointer. 69 | 70 | :returns: Offset from start of region, in bytes. 71 | """ 72 | return self.pos 73 | 74 | def read(self, n=0): 75 | """ 76 | Read data. 77 | 78 | :param n: Number of bytes to read. If omitted or zero, 79 | read until end of region. 80 | :returns: An 8-bit string. 81 | """ 82 | if n: 83 | n = min(n, self.length - self.pos) 84 | else: 85 | n = self.length - self.pos 86 | if not n: # EOF 87 | return b"" if "b" in self.fh.mode else "" 88 | self.pos = self.pos + n 89 | return self.fh.read(n) 90 | 91 | def readline(self): 92 | """ 93 | Read a line of text. 94 | 95 | :returns: An 8-bit string. 96 | """ 97 | s = b"" if "b" in self.fh.mode else "" 98 | newline_character = b"\n" if "b" in self.fh.mode else "\n" 99 | while True: 100 | c = self.read(1) 101 | if not c: 102 | break 103 | s = s + c 104 | if c == newline_character: 105 | break 106 | return s 107 | 108 | def readlines(self): 109 | """ 110 | Read multiple lines of text. 111 | 112 | :returns: A list of 8-bit strings. 113 | """ 114 | lines = [] 115 | while True: 116 | s = self.readline() 117 | if not s: 118 | break 119 | lines.append(s) 120 | return lines 121 | -------------------------------------------------------------------------------- /.site-packages/PIL/CurImagePlugin.py: -------------------------------------------------------------------------------- 1 | # 2 | # The Python Imaging Library. 3 | # $Id$ 4 | # 5 | # Windows Cursor support for PIL 6 | # 7 | # notes: 8 | # uses BmpImagePlugin.py to read the bitmap data. 9 | # 10 | # history: 11 | # 96-05-27 fl Created 12 | # 13 | # Copyright (c) Secret Labs AB 1997. 14 | # Copyright (c) Fredrik Lundh 1996. 15 | # 16 | # See the README file for information on usage and redistribution. 17 | # 18 | from . import BmpImagePlugin, Image 19 | from ._binary import i16le as i16 20 | from ._binary import i32le as i32 21 | 22 | # 23 | # -------------------------------------------------------------------- 24 | 25 | 26 | def _accept(prefix): 27 | return prefix[:4] == b"\0\0\2\0" 28 | 29 | 30 | ## 31 | # Image plugin for Windows Cursor files. 32 | 33 | 34 | class CurImageFile(BmpImagePlugin.BmpImageFile): 35 | 36 | format = "CUR" 37 | format_description = "Windows Cursor" 38 | 39 | def _open(self): 40 | 41 | offset = self.fp.tell() 42 | 43 | # check magic 44 | s = self.fp.read(6) 45 | if not _accept(s): 46 | raise SyntaxError("not a CUR file") 47 | 48 | # pick the largest cursor in the file 49 | m = b"" 50 | for i in range(i16(s, 4)): 51 | s = self.fp.read(16) 52 | if not m: 53 | m = s 54 | elif s[0] > m[0] and s[1] > m[1]: 55 | m = s 56 | if not m: 57 | raise TypeError("No cursors were found") 58 | 59 | # load as bitmap 60 | self._bitmap(i32(m, 12) + offset) 61 | 62 | # patch up the bitmap height 63 | self._size = self.size[0], self.size[1] // 2 64 | d, e, o, a = self.tile[0] 65 | self.tile[0] = d, (0, 0) + self.size, o, a 66 | 67 | return 68 | 69 | 70 | # 71 | # -------------------------------------------------------------------- 72 | 73 | Image.register_open(CurImageFile.format, CurImageFile, _accept) 74 | 75 | Image.register_extension(CurImageFile.format, ".cur") 76 | -------------------------------------------------------------------------------- /.site-packages/PIL/DcxImagePlugin.py: -------------------------------------------------------------------------------- 1 | # 2 | # The Python Imaging Library. 3 | # $Id$ 4 | # 5 | # DCX file handling 6 | # 7 | # DCX is a container file format defined by Intel, commonly used 8 | # for fax applications. Each DCX file consists of a directory 9 | # (a list of file offsets) followed by a set of (usually 1-bit) 10 | # PCX files. 11 | # 12 | # History: 13 | # 1995-09-09 fl Created 14 | # 1996-03-20 fl Properly derived from PcxImageFile. 15 | # 1998-07-15 fl Renamed offset attribute to avoid name clash 16 | # 2002-07-30 fl Fixed file handling 17 | # 18 | # Copyright (c) 1997-98 by Secret Labs AB. 19 | # Copyright (c) 1995-96 by Fredrik Lundh. 20 | # 21 | # See the README file for information on usage and redistribution. 22 | # 23 | 24 | from . import Image 25 | from ._binary import i32le as i32 26 | from .PcxImagePlugin import PcxImageFile 27 | 28 | MAGIC = 0x3ADE68B1 # QUIZ: what's this value, then? 29 | 30 | 31 | def _accept(prefix): 32 | return len(prefix) >= 4 and i32(prefix) == MAGIC 33 | 34 | 35 | ## 36 | # Image plugin for the Intel DCX format. 37 | 38 | 39 | class DcxImageFile(PcxImageFile): 40 | 41 | format = "DCX" 42 | format_description = "Intel DCX" 43 | _close_exclusive_fp_after_loading = False 44 | 45 | def _open(self): 46 | 47 | # Header 48 | s = self.fp.read(4) 49 | if not _accept(s): 50 | raise SyntaxError("not a DCX file") 51 | 52 | # Component directory 53 | self._offset = [] 54 | for i in range(1024): 55 | offset = i32(self.fp.read(4)) 56 | if not offset: 57 | break 58 | self._offset.append(offset) 59 | 60 | self.__fp = self.fp 61 | self.frame = None 62 | self.n_frames = len(self._offset) 63 | self.is_animated = self.n_frames > 1 64 | self.seek(0) 65 | 66 | def seek(self, frame): 67 | if not self._seek_check(frame): 68 | return 69 | self.frame = frame 70 | self.fp = self.__fp 71 | self.fp.seek(self._offset[frame]) 72 | PcxImageFile._open(self) 73 | 74 | def tell(self): 75 | return self.frame 76 | 77 | def _close__fp(self): 78 | try: 79 | if self.__fp != self.fp: 80 | self.__fp.close() 81 | except AttributeError: 82 | pass 83 | finally: 84 | self.__fp = None 85 | 86 | 87 | Image.register_open(DcxImageFile.format, DcxImageFile, _accept) 88 | 89 | Image.register_extension(DcxImageFile.format, ".dcx") 90 | -------------------------------------------------------------------------------- /.site-packages/PIL/FitsImagePlugin.py: -------------------------------------------------------------------------------- 1 | # 2 | # The Python Imaging Library 3 | # $Id$ 4 | # 5 | # FITS file handling 6 | # 7 | # Copyright (c) 1998-2003 by Fredrik Lundh 8 | # 9 | # See the README file for information on usage and redistribution. 10 | # 11 | 12 | import math 13 | 14 | from . import Image, ImageFile 15 | 16 | 17 | def _accept(prefix): 18 | return prefix[:6] == b"SIMPLE" 19 | 20 | 21 | class FitsImageFile(ImageFile.ImageFile): 22 | 23 | format = "FITS" 24 | format_description = "FITS" 25 | 26 | def _open(self): 27 | headers = {} 28 | while True: 29 | header = self.fp.read(80) 30 | if not header: 31 | raise OSError("Truncated FITS file") 32 | keyword = header[:8].strip() 33 | if keyword == b"END": 34 | break 35 | value = header[8:].strip() 36 | if value.startswith(b"="): 37 | value = value[1:].strip() 38 | if not headers and (not _accept(keyword) or value != b"T"): 39 | raise SyntaxError("Not a FITS file") 40 | headers[keyword] = value 41 | 42 | naxis = int(headers[b"NAXIS"]) 43 | if naxis == 0: 44 | raise ValueError("No image data") 45 | elif naxis == 1: 46 | self._size = 1, int(headers[b"NAXIS1"]) 47 | else: 48 | self._size = int(headers[b"NAXIS1"]), int(headers[b"NAXIS2"]) 49 | 50 | number_of_bits = int(headers[b"BITPIX"]) 51 | if number_of_bits == 8: 52 | self.mode = "L" 53 | elif number_of_bits == 16: 54 | self.mode = "I" 55 | # rawmode = "I;16S" 56 | elif number_of_bits == 32: 57 | self.mode = "I" 58 | elif number_of_bits in (-32, -64): 59 | self.mode = "F" 60 | # rawmode = "F" if number_of_bits == -32 else "F;64F" 61 | 62 | offset = math.ceil(self.fp.tell() / 2880) * 2880 63 | self.tile = [("raw", (0, 0) + self.size, offset, (self.mode, 0, -1))] 64 | 65 | 66 | # -------------------------------------------------------------------- 67 | # Registry 68 | 69 | Image.register_open(FitsImageFile.format, FitsImageFile, _accept) 70 | 71 | Image.register_extensions(FitsImageFile.format, [".fit", ".fits"]) 72 | -------------------------------------------------------------------------------- /.site-packages/PIL/FitsStubImagePlugin.py: -------------------------------------------------------------------------------- 1 | # 2 | # The Python Imaging Library 3 | # $Id$ 4 | # 5 | # FITS stub adapter 6 | # 7 | # Copyright (c) 1998-2003 by Fredrik Lundh 8 | # 9 | # See the README file for information on usage and redistribution. 10 | # 11 | 12 | import warnings 13 | 14 | from . import FitsImagePlugin, Image, ImageFile 15 | 16 | _handler = None 17 | 18 | 19 | def register_handler(handler): 20 | """ 21 | Install application-specific FITS image handler. 22 | 23 | :param handler: Handler object. 24 | """ 25 | global _handler 26 | _handler = handler 27 | 28 | warnings.warn( 29 | "FitsStubImagePlugin is deprecated and will be removed in Pillow " 30 | "10 (2023-07-01). FITS images can now be read without a handler through " 31 | "FitsImagePlugin instead.", 32 | DeprecationWarning, 33 | ) 34 | 35 | # Override FitsImagePlugin with this handler 36 | # for backwards compatibility 37 | try: 38 | Image.ID.remove(FITSStubImageFile.format) 39 | except ValueError: 40 | pass 41 | 42 | Image.register_open( 43 | FITSStubImageFile.format, FITSStubImageFile, FitsImagePlugin._accept 44 | ) 45 | 46 | 47 | class FITSStubImageFile(ImageFile.StubImageFile): 48 | 49 | format = FitsImagePlugin.FitsImageFile.format 50 | format_description = FitsImagePlugin.FitsImageFile.format_description 51 | 52 | def _open(self): 53 | offset = self.fp.tell() 54 | 55 | im = FitsImagePlugin.FitsImageFile(self.fp) 56 | self._size = im.size 57 | self.mode = im.mode 58 | self.tile = [] 59 | 60 | self.fp.seek(offset) 61 | 62 | loader = self._load() 63 | if loader: 64 | loader.open(self) 65 | 66 | def _load(self): 67 | return _handler 68 | 69 | 70 | def _save(im, fp, filename): 71 | raise OSError("FITS save handler not installed") 72 | 73 | 74 | # -------------------------------------------------------------------- 75 | # Registry 76 | 77 | Image.register_save(FITSStubImageFile.format, _save) 78 | -------------------------------------------------------------------------------- /.site-packages/PIL/FliImagePlugin.py: -------------------------------------------------------------------------------- 1 | # 2 | # The Python Imaging Library. 3 | # $Id$ 4 | # 5 | # FLI/FLC file handling. 6 | # 7 | # History: 8 | # 95-09-01 fl Created 9 | # 97-01-03 fl Fixed parser, setup decoder tile 10 | # 98-07-15 fl Renamed offset attribute to avoid name clash 11 | # 12 | # Copyright (c) Secret Labs AB 1997-98. 13 | # Copyright (c) Fredrik Lundh 1995-97. 14 | # 15 | # See the README file for information on usage and redistribution. 16 | # 17 | 18 | 19 | from . import Image, ImageFile, ImagePalette 20 | from ._binary import i16le as i16 21 | from ._binary import i32le as i32 22 | from ._binary import o8 23 | 24 | # 25 | # decoder 26 | 27 | 28 | def _accept(prefix): 29 | return ( 30 | len(prefix) >= 6 31 | and i16(prefix, 4) in [0xAF11, 0xAF12] 32 | and i16(prefix, 14) in [0, 3] # flags 33 | ) 34 | 35 | 36 | ## 37 | # Image plugin for the FLI/FLC animation format. Use the seek 38 | # method to load individual frames. 39 | 40 | 41 | class FliImageFile(ImageFile.ImageFile): 42 | 43 | format = "FLI" 44 | format_description = "Autodesk FLI/FLC Animation" 45 | _close_exclusive_fp_after_loading = False 46 | 47 | def _open(self): 48 | 49 | # HEAD 50 | s = self.fp.read(128) 51 | if not (_accept(s) and s[20:22] == b"\x00\x00"): 52 | raise SyntaxError("not an FLI/FLC file") 53 | 54 | # frames 55 | self.n_frames = i16(s, 6) 56 | self.is_animated = self.n_frames > 1 57 | 58 | # image characteristics 59 | self.mode = "P" 60 | self._size = i16(s, 8), i16(s, 10) 61 | 62 | # animation speed 63 | duration = i32(s, 16) 64 | magic = i16(s, 4) 65 | if magic == 0xAF11: 66 | duration = (duration * 1000) // 70 67 | self.info["duration"] = duration 68 | 69 | # look for palette 70 | palette = [(a, a, a) for a in range(256)] 71 | 72 | s = self.fp.read(16) 73 | 74 | self.__offset = 128 75 | 76 | if i16(s, 4) == 0xF100: 77 | # prefix chunk; ignore it 78 | self.__offset = self.__offset + i32(s) 79 | s = self.fp.read(16) 80 | 81 | if i16(s, 4) == 0xF1FA: 82 | # look for palette chunk 83 | s = self.fp.read(6) 84 | if i16(s, 4) == 11: 85 | self._palette(palette, 2) 86 | elif i16(s, 4) == 4: 87 | self._palette(palette, 0) 88 | 89 | palette = [o8(r) + o8(g) + o8(b) for (r, g, b) in palette] 90 | self.palette = ImagePalette.raw("RGB", b"".join(palette)) 91 | 92 | # set things up to decode first frame 93 | self.__frame = -1 94 | self.__fp = self.fp 95 | self.__rewind = self.fp.tell() 96 | self.seek(0) 97 | 98 | def _palette(self, palette, shift): 99 | # load palette 100 | 101 | i = 0 102 | for e in range(i16(self.fp.read(2))): 103 | s = self.fp.read(2) 104 | i = i + s[0] 105 | n = s[1] 106 | if n == 0: 107 | n = 256 108 | s = self.fp.read(n * 3) 109 | for n in range(0, len(s), 3): 110 | r = s[n] << shift 111 | g = s[n + 1] << shift 112 | b = s[n + 2] << shift 113 | palette[i] = (r, g, b) 114 | i += 1 115 | 116 | def seek(self, frame): 117 | if not self._seek_check(frame): 118 | return 119 | if frame < self.__frame: 120 | self._seek(0) 121 | 122 | for f in range(self.__frame + 1, frame + 1): 123 | self._seek(f) 124 | 125 | def _seek(self, frame): 126 | if frame == 0: 127 | self.__frame = -1 128 | self.__fp.seek(self.__rewind) 129 | self.__offset = 128 130 | else: 131 | # ensure that the previous frame was loaded 132 | self.load() 133 | 134 | if frame != self.__frame + 1: 135 | raise ValueError(f"cannot seek to frame {frame}") 136 | self.__frame = frame 137 | 138 | # move to next frame 139 | self.fp = self.__fp 140 | self.fp.seek(self.__offset) 141 | 142 | s = self.fp.read(4) 143 | if not s: 144 | raise EOFError 145 | 146 | framesize = i32(s) 147 | 148 | self.decodermaxblock = framesize 149 | self.tile = [("fli", (0, 0) + self.size, self.__offset, None)] 150 | 151 | self.__offset += framesize 152 | 153 | def tell(self): 154 | return self.__frame 155 | 156 | def _close__fp(self): 157 | try: 158 | if self.__fp != self.fp: 159 | self.__fp.close() 160 | except AttributeError: 161 | pass 162 | finally: 163 | self.__fp = None 164 | 165 | 166 | # 167 | # registry 168 | 169 | Image.register_open(FliImageFile.format, FliImageFile, _accept) 170 | 171 | Image.register_extensions(FliImageFile.format, [".fli", ".flc"]) 172 | -------------------------------------------------------------------------------- /.site-packages/PIL/FontFile.py: -------------------------------------------------------------------------------- 1 | # 2 | # The Python Imaging Library 3 | # $Id$ 4 | # 5 | # base class for raster font file parsers 6 | # 7 | # history: 8 | # 1997-06-05 fl created 9 | # 1997-08-19 fl restrict image width 10 | # 11 | # Copyright (c) 1997-1998 by Secret Labs AB 12 | # Copyright (c) 1997-1998 by Fredrik Lundh 13 | # 14 | # See the README file for information on usage and redistribution. 15 | # 16 | 17 | 18 | import os 19 | 20 | from . import Image, _binary 21 | 22 | WIDTH = 800 23 | 24 | 25 | def puti16(fp, values): 26 | """Write network order (big-endian) 16-bit sequence""" 27 | for v in values: 28 | if v < 0: 29 | v += 65536 30 | fp.write(_binary.o16be(v)) 31 | 32 | 33 | class FontFile: 34 | """Base class for raster font file handlers.""" 35 | 36 | bitmap = None 37 | 38 | def __init__(self): 39 | 40 | self.info = {} 41 | self.glyph = [None] * 256 42 | 43 | def __getitem__(self, ix): 44 | return self.glyph[ix] 45 | 46 | def compile(self): 47 | """Create metrics and bitmap""" 48 | 49 | if self.bitmap: 50 | return 51 | 52 | # create bitmap large enough to hold all data 53 | h = w = maxwidth = 0 54 | lines = 1 55 | for glyph in self: 56 | if glyph: 57 | d, dst, src, im = glyph 58 | h = max(h, src[3] - src[1]) 59 | w = w + (src[2] - src[0]) 60 | if w > WIDTH: 61 | lines += 1 62 | w = src[2] - src[0] 63 | maxwidth = max(maxwidth, w) 64 | 65 | xsize = maxwidth 66 | ysize = lines * h 67 | 68 | if xsize == 0 and ysize == 0: 69 | return "" 70 | 71 | self.ysize = h 72 | 73 | # paste glyphs into bitmap 74 | self.bitmap = Image.new("1", (xsize, ysize)) 75 | self.metrics = [None] * 256 76 | x = y = 0 77 | for i in range(256): 78 | glyph = self[i] 79 | if glyph: 80 | d, dst, src, im = glyph 81 | xx = src[2] - src[0] 82 | # yy = src[3] - src[1] 83 | x0, y0 = x, y 84 | x = x + xx 85 | if x > WIDTH: 86 | x, y = 0, y + h 87 | x0, y0 = x, y 88 | x = xx 89 | s = src[0] + x0, src[1] + y0, src[2] + x0, src[3] + y0 90 | self.bitmap.paste(im.crop(src), s) 91 | self.metrics[i] = d, dst, s 92 | 93 | def save(self, filename): 94 | """Save font""" 95 | 96 | self.compile() 97 | 98 | # font data 99 | self.bitmap.save(os.path.splitext(filename)[0] + ".pbm", "PNG") 100 | 101 | # font metrics 102 | with open(os.path.splitext(filename)[0] + ".pil", "wb") as fp: 103 | fp.write(b"PILfont\n") 104 | fp.write(f";;;;;;{self.ysize};\n".encode("ascii")) # HACK!!! 105 | fp.write(b"DATA\n") 106 | for id in range(256): 107 | m = self.metrics[id] 108 | if not m: 109 | puti16(fp, [0] * 10) 110 | else: 111 | puti16(fp, m[0] + m[1] + m[2]) 112 | -------------------------------------------------------------------------------- /.site-packages/PIL/FtexImagePlugin.py: -------------------------------------------------------------------------------- 1 | """ 2 | A Pillow loader for .ftc and .ftu files (FTEX) 3 | Jerome Leclanche 4 | 5 | The contents of this file are hereby released in the public domain (CC0) 6 | Full text of the CC0 license: 7 | https://creativecommons.org/publicdomain/zero/1.0/ 8 | 9 | Independence War 2: Edge Of Chaos - Texture File Format - 16 October 2001 10 | 11 | The textures used for 3D objects in Independence War 2: Edge Of Chaos are in a 12 | packed custom format called FTEX. This file format uses file extensions FTC 13 | and FTU. 14 | * FTC files are compressed textures (using standard texture compression). 15 | * FTU files are not compressed. 16 | Texture File Format 17 | The FTC and FTU texture files both use the same format. This 18 | has the following structure: 19 | {header} 20 | {format_directory} 21 | {data} 22 | Where: 23 | {header} = { 24 | u32:magic, 25 | u32:version, 26 | u32:width, 27 | u32:height, 28 | u32:mipmap_count, 29 | u32:format_count 30 | } 31 | 32 | * The "magic" number is "FTEX". 33 | * "width" and "height" are the dimensions of the texture. 34 | * "mipmap_count" is the number of mipmaps in the texture. 35 | * "format_count" is the number of texture formats (different versions of the 36 | same texture) in this file. 37 | 38 | {format_directory} = format_count * { u32:format, u32:where } 39 | 40 | The format value is 0 for DXT1 compressed textures and 1 for 24-bit RGB 41 | uncompressed textures. 42 | The texture data for a format starts at the position "where" in the file. 43 | 44 | Each set of texture data in the file has the following structure: 45 | {data} = format_count * { u32:mipmap_size, mipmap_size * { u8 } } 46 | * "mipmap_size" is the number of bytes in that mip level. For compressed 47 | textures this is the size of the texture data compressed with DXT1. For 24 bit 48 | uncompressed textures, this is 3 * width * height. Following this are the image 49 | bytes for that mipmap level. 50 | 51 | Note: All data is stored in little-Endian (Intel) byte order. 52 | """ 53 | 54 | import struct 55 | import warnings 56 | from enum import IntEnum 57 | from io import BytesIO 58 | 59 | from . import Image, ImageFile 60 | 61 | MAGIC = b"FTEX" 62 | 63 | 64 | class Format(IntEnum): 65 | DXT1 = 0 66 | UNCOMPRESSED = 1 67 | 68 | 69 | def __getattr__(name): 70 | deprecated = "deprecated and will be removed in Pillow 10 (2023-07-01). " 71 | for enum, prefix in {Format: "FORMAT_"}.items(): 72 | if name.startswith(prefix): 73 | name = name[len(prefix) :] 74 | if name in enum.__members__: 75 | warnings.warn( 76 | prefix 77 | + name 78 | + " is " 79 | + deprecated 80 | + "Use " 81 | + enum.__name__ 82 | + "." 83 | + name 84 | + " instead.", 85 | DeprecationWarning, 86 | stacklevel=2, 87 | ) 88 | return enum[name] 89 | raise AttributeError(f"module '{__name__}' has no attribute '{name}'") 90 | 91 | 92 | class FtexImageFile(ImageFile.ImageFile): 93 | format = "FTEX" 94 | format_description = "Texture File Format (IW2:EOC)" 95 | 96 | def _open(self): 97 | if not _accept(self.fp.read(4)): 98 | raise SyntaxError("not an FTEX file") 99 | struct.unpack("= 8 and i32(prefix, 0) >= 20 and i32(prefix, 4) in (1, 2) 33 | 34 | 35 | ## 36 | # Image plugin for the GIMP brush format. 37 | 38 | 39 | class GbrImageFile(ImageFile.ImageFile): 40 | 41 | format = "GBR" 42 | format_description = "GIMP brush file" 43 | 44 | def _open(self): 45 | header_size = i32(self.fp.read(4)) 46 | if header_size < 20: 47 | raise SyntaxError("not a GIMP brush") 48 | version = i32(self.fp.read(4)) 49 | if version not in (1, 2): 50 | raise SyntaxError(f"Unsupported GIMP brush version: {version}") 51 | 52 | width = i32(self.fp.read(4)) 53 | height = i32(self.fp.read(4)) 54 | color_depth = i32(self.fp.read(4)) 55 | if width <= 0 or height <= 0: 56 | raise SyntaxError("not a GIMP brush") 57 | if color_depth not in (1, 4): 58 | raise SyntaxError(f"Unsupported GIMP brush color depth: {color_depth}") 59 | 60 | if version == 1: 61 | comment_length = header_size - 20 62 | else: 63 | comment_length = header_size - 28 64 | magic_number = self.fp.read(4) 65 | if magic_number != b"GIMP": 66 | raise SyntaxError("not a GIMP brush, bad magic number") 67 | self.info["spacing"] = i32(self.fp.read(4)) 68 | 69 | comment = self.fp.read(comment_length)[:-1] 70 | 71 | if color_depth == 1: 72 | self.mode = "L" 73 | else: 74 | self.mode = "RGBA" 75 | 76 | self._size = width, height 77 | 78 | self.info["comment"] = comment 79 | 80 | # Image might not be small 81 | Image._decompression_bomb_check(self.size) 82 | 83 | # Data is an uncompressed block of w * h * bytes/pixel 84 | self._data_size = width * height * color_depth 85 | 86 | def load(self): 87 | if not self.im: 88 | self.im = Image.core.new(self.mode, self.size) 89 | self.frombytes(self.fp.read(self._data_size)) 90 | return Image.Image.load(self) 91 | 92 | 93 | # 94 | # registry 95 | 96 | 97 | Image.register_open(GbrImageFile.format, GbrImageFile, _accept) 98 | Image.register_extension(GbrImageFile.format, ".gbr") 99 | -------------------------------------------------------------------------------- /.site-packages/PIL/GdImageFile.py: -------------------------------------------------------------------------------- 1 | # 2 | # The Python Imaging Library. 3 | # $Id$ 4 | # 5 | # GD file handling 6 | # 7 | # History: 8 | # 1996-04-12 fl Created 9 | # 10 | # Copyright (c) 1997 by Secret Labs AB. 11 | # Copyright (c) 1996 by Fredrik Lundh. 12 | # 13 | # See the README file for information on usage and redistribution. 14 | # 15 | 16 | 17 | """ 18 | .. note:: 19 | This format cannot be automatically recognized, so the 20 | class is not registered for use with :py:func:`PIL.Image.open()`. To open a 21 | gd file, use the :py:func:`PIL.GdImageFile.open()` function instead. 22 | 23 | .. warning:: 24 | THE GD FORMAT IS NOT DESIGNED FOR DATA INTERCHANGE. This 25 | implementation is provided for convenience and demonstrational 26 | purposes only. 27 | """ 28 | 29 | 30 | from . import ImageFile, ImagePalette, UnidentifiedImageError 31 | from ._binary import i16be as i16 32 | from ._binary import i32be as i32 33 | 34 | 35 | class GdImageFile(ImageFile.ImageFile): 36 | """ 37 | Image plugin for the GD uncompressed format. Note that this format 38 | is not supported by the standard :py:func:`PIL.Image.open()` function. To use 39 | this plugin, you have to import the :py:mod:`PIL.GdImageFile` module and 40 | use the :py:func:`PIL.GdImageFile.open()` function. 41 | """ 42 | 43 | format = "GD" 44 | format_description = "GD uncompressed images" 45 | 46 | def _open(self): 47 | 48 | # Header 49 | s = self.fp.read(1037) 50 | 51 | if not i16(s) in [65534, 65535]: 52 | raise SyntaxError("Not a valid GD 2.x .gd file") 53 | 54 | self.mode = "L" # FIXME: "P" 55 | self._size = i16(s, 2), i16(s, 4) 56 | 57 | trueColor = s[6] 58 | trueColorOffset = 2 if trueColor else 0 59 | 60 | # transparency index 61 | tindex = i32(s, 7 + trueColorOffset) 62 | if tindex < 256: 63 | self.info["transparency"] = tindex 64 | 65 | self.palette = ImagePalette.raw( 66 | "XBGR", s[7 + trueColorOffset + 4 : 7 + trueColorOffset + 4 + 256 * 4] 67 | ) 68 | 69 | self.tile = [ 70 | ("raw", (0, 0) + self.size, 7 + trueColorOffset + 4 + 256 * 4, ("L", 0, 1)) 71 | ] 72 | 73 | 74 | def open(fp, mode="r"): 75 | """ 76 | Load texture from a GD image file. 77 | 78 | :param filename: GD file name, or an opened file handle. 79 | :param mode: Optional mode. In this version, if the mode argument 80 | is given, it must be "r". 81 | :returns: An image instance. 82 | :raises OSError: If the image could not be read. 83 | """ 84 | if mode != "r": 85 | raise ValueError("bad mode") 86 | 87 | try: 88 | return GdImageFile(fp) 89 | except SyntaxError as e: 90 | raise UnidentifiedImageError("cannot identify this image file") from e 91 | -------------------------------------------------------------------------------- /.site-packages/PIL/GimpGradientFile.py: -------------------------------------------------------------------------------- 1 | # 2 | # Python Imaging Library 3 | # $Id$ 4 | # 5 | # stuff to read (and render) GIMP gradient files 6 | # 7 | # History: 8 | # 97-08-23 fl Created 9 | # 10 | # Copyright (c) Secret Labs AB 1997. 11 | # Copyright (c) Fredrik Lundh 1997. 12 | # 13 | # See the README file for information on usage and redistribution. 14 | # 15 | 16 | """ 17 | Stuff to translate curve segments to palette values (derived from 18 | the corresponding code in GIMP, written by Federico Mena Quintero. 19 | See the GIMP distribution for more information.) 20 | """ 21 | 22 | 23 | from math import log, pi, sin, sqrt 24 | 25 | from ._binary import o8 26 | 27 | EPSILON = 1e-10 28 | """""" # Enable auto-doc for data member 29 | 30 | 31 | def linear(middle, pos): 32 | if pos <= middle: 33 | if middle < EPSILON: 34 | return 0.0 35 | else: 36 | return 0.5 * pos / middle 37 | else: 38 | pos = pos - middle 39 | middle = 1.0 - middle 40 | if middle < EPSILON: 41 | return 1.0 42 | else: 43 | return 0.5 + 0.5 * pos / middle 44 | 45 | 46 | def curved(middle, pos): 47 | return pos ** (log(0.5) / log(max(middle, EPSILON))) 48 | 49 | 50 | def sine(middle, pos): 51 | return (sin((-pi / 2.0) + pi * linear(middle, pos)) + 1.0) / 2.0 52 | 53 | 54 | def sphere_increasing(middle, pos): 55 | return sqrt(1.0 - (linear(middle, pos) - 1.0) ** 2) 56 | 57 | 58 | def sphere_decreasing(middle, pos): 59 | return 1.0 - sqrt(1.0 - linear(middle, pos) ** 2) 60 | 61 | 62 | SEGMENTS = [linear, curved, sine, sphere_increasing, sphere_decreasing] 63 | """""" # Enable auto-doc for data member 64 | 65 | 66 | class GradientFile: 67 | 68 | gradient = None 69 | 70 | def getpalette(self, entries=256): 71 | 72 | palette = [] 73 | 74 | ix = 0 75 | x0, x1, xm, rgb0, rgb1, segment = self.gradient[ix] 76 | 77 | for i in range(entries): 78 | 79 | x = i / (entries - 1) 80 | 81 | while x1 < x: 82 | ix += 1 83 | x0, x1, xm, rgb0, rgb1, segment = self.gradient[ix] 84 | 85 | w = x1 - x0 86 | 87 | if w < EPSILON: 88 | scale = segment(0.5, 0.5) 89 | else: 90 | scale = segment((xm - x0) / w, (x - x0) / w) 91 | 92 | # expand to RGBA 93 | r = o8(int(255 * ((rgb1[0] - rgb0[0]) * scale + rgb0[0]) + 0.5)) 94 | g = o8(int(255 * ((rgb1[1] - rgb0[1]) * scale + rgb0[1]) + 0.5)) 95 | b = o8(int(255 * ((rgb1[2] - rgb0[2]) * scale + rgb0[2]) + 0.5)) 96 | a = o8(int(255 * ((rgb1[3] - rgb0[3]) * scale + rgb0[3]) + 0.5)) 97 | 98 | # add to palette 99 | palette.append(r + g + b + a) 100 | 101 | return b"".join(palette), "RGBA" 102 | 103 | 104 | class GimpGradientFile(GradientFile): 105 | """File handler for GIMP's gradient format.""" 106 | 107 | def __init__(self, fp): 108 | 109 | if fp.readline()[:13] != b"GIMP Gradient": 110 | raise SyntaxError("not a GIMP gradient file") 111 | 112 | line = fp.readline() 113 | 114 | # GIMP 1.2 gradient files don't contain a name, but GIMP 1.3 files do 115 | if line.startswith(b"Name: "): 116 | line = fp.readline().strip() 117 | 118 | count = int(line) 119 | 120 | gradient = [] 121 | 122 | for i in range(count): 123 | 124 | s = fp.readline().split() 125 | w = [float(x) for x in s[:11]] 126 | 127 | x0, x1 = w[0], w[2] 128 | xm = w[1] 129 | rgb0 = w[3:7] 130 | rgb1 = w[7:11] 131 | 132 | segment = SEGMENTS[int(s[11])] 133 | cspace = int(s[12]) 134 | 135 | if cspace != 0: 136 | raise OSError("cannot handle HSV colour space") 137 | 138 | gradient.append((x0, x1, xm, rgb0, rgb1, segment)) 139 | 140 | self.gradient = gradient 141 | -------------------------------------------------------------------------------- /.site-packages/PIL/GimpPaletteFile.py: -------------------------------------------------------------------------------- 1 | # 2 | # Python Imaging Library 3 | # $Id$ 4 | # 5 | # stuff to read GIMP palette files 6 | # 7 | # History: 8 | # 1997-08-23 fl Created 9 | # 2004-09-07 fl Support GIMP 2.0 palette files. 10 | # 11 | # Copyright (c) Secret Labs AB 1997-2004. All rights reserved. 12 | # Copyright (c) Fredrik Lundh 1997-2004. 13 | # 14 | # See the README file for information on usage and redistribution. 15 | # 16 | 17 | import re 18 | 19 | from ._binary import o8 20 | 21 | 22 | class GimpPaletteFile: 23 | """File handler for GIMP's palette format.""" 24 | 25 | rawmode = "RGB" 26 | 27 | def __init__(self, fp): 28 | 29 | self.palette = [o8(i) * 3 for i in range(256)] 30 | 31 | if fp.readline()[:12] != b"GIMP Palette": 32 | raise SyntaxError("not a GIMP palette file") 33 | 34 | for i in range(256): 35 | 36 | s = fp.readline() 37 | if not s: 38 | break 39 | 40 | # skip fields and comment lines 41 | if re.match(rb"\w+:|#", s): 42 | continue 43 | if len(s) > 100: 44 | raise SyntaxError("bad palette file") 45 | 46 | v = tuple(map(int, s.split()[:3])) 47 | if len(v) != 3: 48 | raise ValueError("bad palette entry") 49 | 50 | self.palette[i] = o8(v[0]) + o8(v[1]) + o8(v[2]) 51 | 52 | self.palette = b"".join(self.palette) 53 | 54 | def getpalette(self): 55 | 56 | return self.palette, self.rawmode 57 | -------------------------------------------------------------------------------- /.site-packages/PIL/GribStubImagePlugin.py: -------------------------------------------------------------------------------- 1 | # 2 | # The Python Imaging Library 3 | # $Id$ 4 | # 5 | # GRIB stub adapter 6 | # 7 | # Copyright (c) 1996-2003 by Fredrik Lundh 8 | # 9 | # See the README file for information on usage and redistribution. 10 | # 11 | 12 | from . import Image, ImageFile 13 | 14 | _handler = None 15 | 16 | 17 | def register_handler(handler): 18 | """ 19 | Install application-specific GRIB image handler. 20 | 21 | :param handler: Handler object. 22 | """ 23 | global _handler 24 | _handler = handler 25 | 26 | 27 | # -------------------------------------------------------------------- 28 | # Image adapter 29 | 30 | 31 | def _accept(prefix): 32 | return prefix[0:4] == b"GRIB" and prefix[7] == 1 33 | 34 | 35 | class GribStubImageFile(ImageFile.StubImageFile): 36 | 37 | format = "GRIB" 38 | format_description = "GRIB" 39 | 40 | def _open(self): 41 | 42 | offset = self.fp.tell() 43 | 44 | if not _accept(self.fp.read(8)): 45 | raise SyntaxError("Not a GRIB file") 46 | 47 | self.fp.seek(offset) 48 | 49 | # make something up 50 | self.mode = "F" 51 | self._size = 1, 1 52 | 53 | loader = self._load() 54 | if loader: 55 | loader.open(self) 56 | 57 | def _load(self): 58 | return _handler 59 | 60 | 61 | def _save(im, fp, filename): 62 | if _handler is None or not hasattr(_handler, "save"): 63 | raise OSError("GRIB save handler not installed") 64 | _handler.save(im, fp, filename) 65 | 66 | 67 | # -------------------------------------------------------------------- 68 | # Registry 69 | 70 | Image.register_open(GribStubImageFile.format, GribStubImageFile, _accept) 71 | Image.register_save(GribStubImageFile.format, _save) 72 | 73 | Image.register_extension(GribStubImageFile.format, ".grib") 74 | -------------------------------------------------------------------------------- /.site-packages/PIL/Hdf5StubImagePlugin.py: -------------------------------------------------------------------------------- 1 | # 2 | # The Python Imaging Library 3 | # $Id$ 4 | # 5 | # HDF5 stub adapter 6 | # 7 | # Copyright (c) 2000-2003 by Fredrik Lundh 8 | # 9 | # See the README file for information on usage and redistribution. 10 | # 11 | 12 | from . import Image, ImageFile 13 | 14 | _handler = None 15 | 16 | 17 | def register_handler(handler): 18 | """ 19 | Install application-specific HDF5 image handler. 20 | 21 | :param handler: Handler object. 22 | """ 23 | global _handler 24 | _handler = handler 25 | 26 | 27 | # -------------------------------------------------------------------- 28 | # Image adapter 29 | 30 | 31 | def _accept(prefix): 32 | return prefix[:8] == b"\x89HDF\r\n\x1a\n" 33 | 34 | 35 | class HDF5StubImageFile(ImageFile.StubImageFile): 36 | 37 | format = "HDF5" 38 | format_description = "HDF5" 39 | 40 | def _open(self): 41 | 42 | offset = self.fp.tell() 43 | 44 | if not _accept(self.fp.read(8)): 45 | raise SyntaxError("Not an HDF file") 46 | 47 | self.fp.seek(offset) 48 | 49 | # make something up 50 | self.mode = "F" 51 | self._size = 1, 1 52 | 53 | loader = self._load() 54 | if loader: 55 | loader.open(self) 56 | 57 | def _load(self): 58 | return _handler 59 | 60 | 61 | def _save(im, fp, filename): 62 | if _handler is None or not hasattr(_handler, "save"): 63 | raise OSError("HDF5 save handler not installed") 64 | _handler.save(im, fp, filename) 65 | 66 | 67 | # -------------------------------------------------------------------- 68 | # Registry 69 | 70 | Image.register_open(HDF5StubImageFile.format, HDF5StubImageFile, _accept) 71 | Image.register_save(HDF5StubImageFile.format, _save) 72 | 73 | Image.register_extensions(HDF5StubImageFile.format, [".h5", ".hdf"]) 74 | -------------------------------------------------------------------------------- /.site-packages/PIL/ImageDraw2.py: -------------------------------------------------------------------------------- 1 | # 2 | # The Python Imaging Library 3 | # $Id$ 4 | # 5 | # WCK-style drawing interface operations 6 | # 7 | # History: 8 | # 2003-12-07 fl created 9 | # 2005-05-15 fl updated; added to PIL as ImageDraw2 10 | # 2005-05-15 fl added text support 11 | # 2005-05-20 fl added arc/chord/pieslice support 12 | # 13 | # Copyright (c) 2003-2005 by Secret Labs AB 14 | # Copyright (c) 2003-2005 by Fredrik Lundh 15 | # 16 | # See the README file for information on usage and redistribution. 17 | # 18 | 19 | 20 | """ 21 | (Experimental) WCK-style drawing interface operations 22 | 23 | .. seealso:: :py:mod:`PIL.ImageDraw` 24 | """ 25 | 26 | 27 | from . import Image, ImageColor, ImageDraw, ImageFont, ImagePath 28 | 29 | 30 | class Pen: 31 | """Stores an outline color and width.""" 32 | 33 | def __init__(self, color, width=1, opacity=255): 34 | self.color = ImageColor.getrgb(color) 35 | self.width = width 36 | 37 | 38 | class Brush: 39 | """Stores a fill color""" 40 | 41 | def __init__(self, color, opacity=255): 42 | self.color = ImageColor.getrgb(color) 43 | 44 | 45 | class Font: 46 | """Stores a TrueType font and color""" 47 | 48 | def __init__(self, color, file, size=12): 49 | # FIXME: add support for bitmap fonts 50 | self.color = ImageColor.getrgb(color) 51 | self.font = ImageFont.truetype(file, size) 52 | 53 | 54 | class Draw: 55 | """ 56 | (Experimental) WCK-style drawing interface 57 | """ 58 | 59 | def __init__(self, image, size=None, color=None): 60 | if not hasattr(image, "im"): 61 | image = Image.new(image, size, color) 62 | self.draw = ImageDraw.Draw(image) 63 | self.image = image 64 | self.transform = None 65 | 66 | def flush(self): 67 | return self.image 68 | 69 | def render(self, op, xy, pen, brush=None): 70 | # handle color arguments 71 | outline = fill = None 72 | width = 1 73 | if isinstance(pen, Pen): 74 | outline = pen.color 75 | width = pen.width 76 | elif isinstance(brush, Pen): 77 | outline = brush.color 78 | width = brush.width 79 | if isinstance(brush, Brush): 80 | fill = brush.color 81 | elif isinstance(pen, Brush): 82 | fill = pen.color 83 | # handle transformation 84 | if self.transform: 85 | xy = ImagePath.Path(xy) 86 | xy.transform(self.transform) 87 | # render the item 88 | if op == "line": 89 | self.draw.line(xy, fill=outline, width=width) 90 | else: 91 | getattr(self.draw, op)(xy, fill=fill, outline=outline) 92 | 93 | def settransform(self, offset): 94 | """Sets a transformation offset.""" 95 | (xoffset, yoffset) = offset 96 | self.transform = (1, 0, xoffset, 0, 1, yoffset) 97 | 98 | def arc(self, xy, start, end, *options): 99 | """ 100 | Draws an arc (a portion of a circle outline) between the start and end 101 | angles, inside the given bounding box. 102 | 103 | .. seealso:: :py:meth:`PIL.ImageDraw.ImageDraw.arc` 104 | """ 105 | self.render("arc", xy, start, end, *options) 106 | 107 | def chord(self, xy, start, end, *options): 108 | """ 109 | Same as :py:meth:`~PIL.ImageDraw2.Draw.arc`, but connects the end points 110 | with a straight line. 111 | 112 | .. seealso:: :py:meth:`PIL.ImageDraw.ImageDraw.chord` 113 | """ 114 | self.render("chord", xy, start, end, *options) 115 | 116 | def ellipse(self, xy, *options): 117 | """ 118 | Draws an ellipse inside the given bounding box. 119 | 120 | .. seealso:: :py:meth:`PIL.ImageDraw.ImageDraw.ellipse` 121 | """ 122 | self.render("ellipse", xy, *options) 123 | 124 | def line(self, xy, *options): 125 | """ 126 | Draws a line between the coordinates in the ``xy`` list. 127 | 128 | .. seealso:: :py:meth:`PIL.ImageDraw.ImageDraw.line` 129 | """ 130 | self.render("line", xy, *options) 131 | 132 | def pieslice(self, xy, start, end, *options): 133 | """ 134 | Same as arc, but also draws straight lines between the end points and the 135 | center of the bounding box. 136 | 137 | .. seealso:: :py:meth:`PIL.ImageDraw.ImageDraw.pieslice` 138 | """ 139 | self.render("pieslice", xy, start, end, *options) 140 | 141 | def polygon(self, xy, *options): 142 | """ 143 | Draws a polygon. 144 | 145 | The polygon outline consists of straight lines between the given 146 | coordinates, plus a straight line between the last and the first 147 | coordinate. 148 | 149 | 150 | .. seealso:: :py:meth:`PIL.ImageDraw.ImageDraw.polygon` 151 | """ 152 | self.render("polygon", xy, *options) 153 | 154 | def rectangle(self, xy, *options): 155 | """ 156 | Draws a rectangle. 157 | 158 | .. seealso:: :py:meth:`PIL.ImageDraw.ImageDraw.rectangle` 159 | """ 160 | self.render("rectangle", xy, *options) 161 | 162 | def text(self, xy, text, font): 163 | """ 164 | Draws the string at the given position. 165 | 166 | .. seealso:: :py:meth:`PIL.ImageDraw.ImageDraw.text` 167 | """ 168 | if self.transform: 169 | xy = ImagePath.Path(xy) 170 | xy.transform(self.transform) 171 | self.draw.text(xy, text, font=font.font, fill=font.color) 172 | 173 | def textsize(self, text, font): 174 | """ 175 | Return the size of the given string, in pixels. 176 | 177 | .. seealso:: :py:meth:`PIL.ImageDraw.ImageDraw.textsize` 178 | """ 179 | return self.draw.textsize(text, font=font.font) 180 | -------------------------------------------------------------------------------- /.site-packages/PIL/ImageEnhance.py: -------------------------------------------------------------------------------- 1 | # 2 | # The Python Imaging Library. 3 | # $Id$ 4 | # 5 | # image enhancement classes 6 | # 7 | # For a background, see "Image Processing By Interpolation and 8 | # Extrapolation", Paul Haeberli and Douglas Voorhies. Available 9 | # at http://www.graficaobscura.com/interp/index.html 10 | # 11 | # History: 12 | # 1996-03-23 fl Created 13 | # 2009-06-16 fl Fixed mean calculation 14 | # 15 | # Copyright (c) Secret Labs AB 1997. 16 | # Copyright (c) Fredrik Lundh 1996. 17 | # 18 | # See the README file for information on usage and redistribution. 19 | # 20 | 21 | from . import Image, ImageFilter, ImageStat 22 | 23 | 24 | class _Enhance: 25 | def enhance(self, factor): 26 | """ 27 | Returns an enhanced image. 28 | 29 | :param factor: A floating point value controlling the enhancement. 30 | Factor 1.0 always returns a copy of the original image, 31 | lower factors mean less color (brightness, contrast, 32 | etc), and higher values more. There are no restrictions 33 | on this value. 34 | :rtype: :py:class:`~PIL.Image.Image` 35 | """ 36 | return Image.blend(self.degenerate, self.image, factor) 37 | 38 | 39 | class Color(_Enhance): 40 | """Adjust image color balance. 41 | 42 | This class can be used to adjust the colour balance of an image, in 43 | a manner similar to the controls on a colour TV set. An enhancement 44 | factor of 0.0 gives a black and white image. A factor of 1.0 gives 45 | the original image. 46 | """ 47 | 48 | def __init__(self, image): 49 | self.image = image 50 | self.intermediate_mode = "L" 51 | if "A" in image.getbands(): 52 | self.intermediate_mode = "LA" 53 | 54 | self.degenerate = image.convert(self.intermediate_mode).convert(image.mode) 55 | 56 | 57 | class Contrast(_Enhance): 58 | """Adjust image contrast. 59 | 60 | This class can be used to control the contrast of an image, similar 61 | to the contrast control on a TV set. An enhancement factor of 0.0 62 | gives a solid grey image. A factor of 1.0 gives the original image. 63 | """ 64 | 65 | def __init__(self, image): 66 | self.image = image 67 | mean = int(ImageStat.Stat(image.convert("L")).mean[0] + 0.5) 68 | self.degenerate = Image.new("L", image.size, mean).convert(image.mode) 69 | 70 | if "A" in image.getbands(): 71 | self.degenerate.putalpha(image.getchannel("A")) 72 | 73 | 74 | class Brightness(_Enhance): 75 | """Adjust image brightness. 76 | 77 | This class can be used to control the brightness of an image. An 78 | enhancement factor of 0.0 gives a black image. A factor of 1.0 gives the 79 | original image. 80 | """ 81 | 82 | def __init__(self, image): 83 | self.image = image 84 | self.degenerate = Image.new(image.mode, image.size, 0) 85 | 86 | if "A" in image.getbands(): 87 | self.degenerate.putalpha(image.getchannel("A")) 88 | 89 | 90 | class Sharpness(_Enhance): 91 | """Adjust image sharpness. 92 | 93 | This class can be used to adjust the sharpness of an image. An 94 | enhancement factor of 0.0 gives a blurred image, a factor of 1.0 gives the 95 | original image, and a factor of 2.0 gives a sharpened image. 96 | """ 97 | 98 | def __init__(self, image): 99 | self.image = image 100 | self.degenerate = image.filter(ImageFilter.SMOOTH) 101 | 102 | if "A" in image.getbands(): 103 | self.degenerate.putalpha(image.getchannel("A")) 104 | -------------------------------------------------------------------------------- /.site-packages/PIL/ImageGrab.py: -------------------------------------------------------------------------------- 1 | # 2 | # The Python Imaging Library 3 | # $Id$ 4 | # 5 | # screen grabber 6 | # 7 | # History: 8 | # 2001-04-26 fl created 9 | # 2001-09-17 fl use builtin driver, if present 10 | # 2002-11-19 fl added grabclipboard support 11 | # 12 | # Copyright (c) 2001-2002 by Secret Labs AB 13 | # Copyright (c) 2001-2002 by Fredrik Lundh 14 | # 15 | # See the README file for information on usage and redistribution. 16 | # 17 | 18 | import sys 19 | 20 | from . import Image 21 | 22 | if sys.platform == "darwin": 23 | import os 24 | import subprocess 25 | import tempfile 26 | 27 | 28 | def grab(bbox=None, include_layered_windows=False, all_screens=False, xdisplay=None): 29 | if xdisplay is None: 30 | if sys.platform == "darwin": 31 | fh, filepath = tempfile.mkstemp(".png") 32 | os.close(fh) 33 | args = ["screencapture"] 34 | if bbox: 35 | left, top, right, bottom = bbox 36 | args += ["-R", f"{left},{right},{right-left},{bottom-top}"] 37 | subprocess.call(args + ["-x", filepath]) 38 | im = Image.open(filepath) 39 | im.load() 40 | os.unlink(filepath) 41 | if bbox: 42 | im_resized = im.resize((right - left, bottom - top)) 43 | im.close() 44 | return im_resized 45 | return im 46 | elif sys.platform == "win32": 47 | offset, size, data = Image.core.grabscreen_win32( 48 | include_layered_windows, all_screens 49 | ) 50 | im = Image.frombytes( 51 | "RGB", 52 | size, 53 | data, 54 | # RGB, 32-bit line padding, origin lower left corner 55 | "raw", 56 | "BGR", 57 | (size[0] * 3 + 3) & -4, 58 | -1, 59 | ) 60 | if bbox: 61 | x0, y0 = offset 62 | left, top, right, bottom = bbox 63 | im = im.crop((left - x0, top - y0, right - x0, bottom - y0)) 64 | return im 65 | # use xdisplay=None for default display on non-win32/macOS systems 66 | if not Image.core.HAVE_XCB: 67 | raise OSError("Pillow was built without XCB support") 68 | size, data = Image.core.grabscreen_x11(xdisplay) 69 | im = Image.frombytes("RGB", size, data, "raw", "BGRX", size[0] * 4, 1) 70 | if bbox: 71 | im = im.crop(bbox) 72 | return im 73 | 74 | 75 | def grabclipboard(): 76 | if sys.platform == "darwin": 77 | fh, filepath = tempfile.mkstemp(".jpg") 78 | os.close(fh) 79 | commands = [ 80 | 'set theFile to (open for access POSIX file "' 81 | + filepath 82 | + '" with write permission)', 83 | "try", 84 | " write (the clipboard as JPEG picture) to theFile", 85 | "end try", 86 | "close access theFile", 87 | ] 88 | script = ["osascript"] 89 | for command in commands: 90 | script += ["-e", command] 91 | subprocess.call(script) 92 | 93 | im = None 94 | if os.stat(filepath).st_size != 0: 95 | im = Image.open(filepath) 96 | im.load() 97 | os.unlink(filepath) 98 | return im 99 | elif sys.platform == "win32": 100 | fmt, data = Image.core.grabclipboard_win32() 101 | if fmt == "file": # CF_HDROP 102 | import struct 103 | 104 | o = struct.unpack_from("I", data)[0] 105 | if data[16] != 0: 106 | files = data[o:].decode("utf-16le").split("\0") 107 | else: 108 | files = data[o:].decode("mbcs").split("\0") 109 | return files[: files.index("")] 110 | if isinstance(data, bytes): 111 | import io 112 | 113 | data = io.BytesIO(data) 114 | if fmt == "png": 115 | from . import PngImagePlugin 116 | 117 | return PngImagePlugin.PngImageFile(data) 118 | elif fmt == "DIB": 119 | from . import BmpImagePlugin 120 | 121 | return BmpImagePlugin.DibImageFile(data) 122 | return None 123 | else: 124 | raise NotImplementedError("ImageGrab.grabclipboard() is macOS and Windows only") 125 | -------------------------------------------------------------------------------- /.site-packages/PIL/ImageMode.py: -------------------------------------------------------------------------------- 1 | # 2 | # The Python Imaging Library. 3 | # $Id$ 4 | # 5 | # standard mode descriptors 6 | # 7 | # History: 8 | # 2006-03-20 fl Added 9 | # 10 | # Copyright (c) 2006 by Secret Labs AB. 11 | # Copyright (c) 2006 by Fredrik Lundh. 12 | # 13 | # See the README file for information on usage and redistribution. 14 | # 15 | 16 | import sys 17 | 18 | # mode descriptor cache 19 | _modes = None 20 | 21 | 22 | class ModeDescriptor: 23 | """Wrapper for mode strings.""" 24 | 25 | def __init__(self, mode, bands, basemode, basetype, typestr): 26 | self.mode = mode 27 | self.bands = bands 28 | self.basemode = basemode 29 | self.basetype = basetype 30 | self.typestr = typestr 31 | 32 | def __str__(self): 33 | return self.mode 34 | 35 | 36 | def getmode(mode): 37 | """Gets a mode descriptor for the given mode.""" 38 | global _modes 39 | if not _modes: 40 | # initialize mode cache 41 | modes = {} 42 | endian = "<" if sys.byteorder == "little" else ">" 43 | for m, (basemode, basetype, bands, typestr) in { 44 | # core modes 45 | # Bits need to be extended to bytes 46 | "1": ("L", "L", ("1",), "|b1"), 47 | "L": ("L", "L", ("L",), "|u1"), 48 | "I": ("L", "I", ("I",), endian + "i4"), 49 | "F": ("L", "F", ("F",), endian + "f4"), 50 | "P": ("P", "L", ("P",), "|u1"), 51 | "RGB": ("RGB", "L", ("R", "G", "B"), "|u1"), 52 | "RGBX": ("RGB", "L", ("R", "G", "B", "X"), "|u1"), 53 | "RGBA": ("RGB", "L", ("R", "G", "B", "A"), "|u1"), 54 | "CMYK": ("RGB", "L", ("C", "M", "Y", "K"), "|u1"), 55 | "YCbCr": ("RGB", "L", ("Y", "Cb", "Cr"), "|u1"), 56 | # UNDONE - unsigned |u1i1i1 57 | "LAB": ("RGB", "L", ("L", "A", "B"), "|u1"), 58 | "HSV": ("RGB", "L", ("H", "S", "V"), "|u1"), 59 | # extra experimental modes 60 | "RGBa": ("RGB", "L", ("R", "G", "B", "a"), "|u1"), 61 | "BGR;15": ("RGB", "L", ("B", "G", "R"), endian + "u2"), 62 | "BGR;16": ("RGB", "L", ("B", "G", "R"), endian + "u2"), 63 | "BGR;24": ("RGB", "L", ("B", "G", "R"), endian + "u3"), 64 | "BGR;32": ("RGB", "L", ("B", "G", "R"), endian + "u4"), 65 | "LA": ("L", "L", ("L", "A"), "|u1"), 66 | "La": ("L", "L", ("L", "a"), "|u1"), 67 | "PA": ("RGB", "L", ("P", "A"), "|u1"), 68 | }.items(): 69 | modes[m] = ModeDescriptor(m, bands, basemode, basetype, typestr) 70 | # mapping modes 71 | for i16mode, typestr in { 72 | # I;16 == I;16L, and I;32 == I;32L 73 | "I;16": "u2", 78 | "I;16BS": ">i2", 79 | "I;16N": endian + "u2", 80 | "I;16NS": endian + "i2", 81 | "I;32": "u4", 83 | "I;32L": "i4", 86 | "I;32LS": " half: 117 | break 118 | v.append(j) 119 | return v 120 | 121 | def _getrms(self): 122 | """Get RMS for each layer""" 123 | 124 | v = [] 125 | for i in self.bands: 126 | v.append(math.sqrt(self.sum2[i] / self.count[i])) 127 | return v 128 | 129 | def _getvar(self): 130 | """Get variance for each layer""" 131 | 132 | v = [] 133 | for i in self.bands: 134 | n = self.count[i] 135 | v.append((self.sum2[i] - (self.sum[i] ** 2.0) / n) / n) 136 | return v 137 | 138 | def _getstddev(self): 139 | """Get standard deviation for each layer""" 140 | 141 | v = [] 142 | for i in self.bands: 143 | v.append(math.sqrt(self.var[i])) 144 | return v 145 | 146 | 147 | Global = Stat # compatibility 148 | -------------------------------------------------------------------------------- /.site-packages/PIL/ImageTransform.py: -------------------------------------------------------------------------------- 1 | # 2 | # The Python Imaging Library. 3 | # $Id$ 4 | # 5 | # transform wrappers 6 | # 7 | # History: 8 | # 2002-04-08 fl Created 9 | # 10 | # Copyright (c) 2002 by Secret Labs AB 11 | # Copyright (c) 2002 by Fredrik Lundh 12 | # 13 | # See the README file for information on usage and redistribution. 14 | # 15 | 16 | from . import Image 17 | 18 | 19 | class Transform(Image.ImageTransformHandler): 20 | def __init__(self, data): 21 | self.data = data 22 | 23 | def getdata(self): 24 | return self.method, self.data 25 | 26 | def transform(self, size, image, **options): 27 | # can be overridden 28 | method, data = self.getdata() 29 | return image.transform(size, method, data, **options) 30 | 31 | 32 | class AffineTransform(Transform): 33 | """ 34 | Define an affine image transform. 35 | 36 | This function takes a 6-tuple (a, b, c, d, e, f) which contain the first 37 | two rows from an affine transform matrix. For each pixel (x, y) in the 38 | output image, the new value is taken from a position (a x + b y + c, 39 | d x + e y + f) in the input image, rounded to nearest pixel. 40 | 41 | This function can be used to scale, translate, rotate, and shear the 42 | original image. 43 | 44 | See :py:meth:`~PIL.Image.Image.transform` 45 | 46 | :param matrix: A 6-tuple (a, b, c, d, e, f) containing the first two rows 47 | from an affine transform matrix. 48 | """ 49 | 50 | method = Image.Transform.AFFINE 51 | 52 | 53 | class ExtentTransform(Transform): 54 | """ 55 | Define a transform to extract a subregion from an image. 56 | 57 | Maps a rectangle (defined by two corners) from the image to a rectangle of 58 | the given size. The resulting image will contain data sampled from between 59 | the corners, such that (x0, y0) in the input image will end up at (0,0) in 60 | the output image, and (x1, y1) at size. 61 | 62 | This method can be used to crop, stretch, shrink, or mirror an arbitrary 63 | rectangle in the current image. It is slightly slower than crop, but about 64 | as fast as a corresponding resize operation. 65 | 66 | See :py:meth:`~PIL.Image.Image.transform` 67 | 68 | :param bbox: A 4-tuple (x0, y0, x1, y1) which specifies two points in the 69 | input image's coordinate system. See :ref:`coordinate-system`. 70 | """ 71 | 72 | method = Image.Transform.EXTENT 73 | 74 | 75 | class QuadTransform(Transform): 76 | """ 77 | Define a quad image transform. 78 | 79 | Maps a quadrilateral (a region defined by four corners) from the image to a 80 | rectangle of the given size. 81 | 82 | See :py:meth:`~PIL.Image.Image.transform` 83 | 84 | :param xy: An 8-tuple (x0, y0, x1, y1, x2, y2, x3, y3) which contain the 85 | upper left, lower left, lower right, and upper right corner of the 86 | source quadrilateral. 87 | """ 88 | 89 | method = Image.Transform.QUAD 90 | 91 | 92 | class MeshTransform(Transform): 93 | """ 94 | Define a mesh image transform. A mesh transform consists of one or more 95 | individual quad transforms. 96 | 97 | See :py:meth:`~PIL.Image.Image.transform` 98 | 99 | :param data: A list of (bbox, quad) tuples. 100 | """ 101 | 102 | method = Image.Transform.MESH 103 | -------------------------------------------------------------------------------- /.site-packages/PIL/ImtImagePlugin.py: -------------------------------------------------------------------------------- 1 | # 2 | # The Python Imaging Library. 3 | # $Id$ 4 | # 5 | # IM Tools support for PIL 6 | # 7 | # history: 8 | # 1996-05-27 fl Created (read 8-bit images only) 9 | # 2001-02-17 fl Use 're' instead of 'regex' (Python 2.1) (0.2) 10 | # 11 | # Copyright (c) Secret Labs AB 1997-2001. 12 | # Copyright (c) Fredrik Lundh 1996-2001. 13 | # 14 | # See the README file for information on usage and redistribution. 15 | # 16 | 17 | 18 | import re 19 | 20 | from . import Image, ImageFile 21 | 22 | # 23 | # -------------------------------------------------------------------- 24 | 25 | field = re.compile(rb"([a-z]*) ([^ \r\n]*)") 26 | 27 | 28 | ## 29 | # Image plugin for IM Tools images. 30 | 31 | 32 | class ImtImageFile(ImageFile.ImageFile): 33 | 34 | format = "IMT" 35 | format_description = "IM Tools" 36 | 37 | def _open(self): 38 | 39 | # Quick rejection: if there's not a LF among the first 40 | # 100 bytes, this is (probably) not a text header. 41 | 42 | if b"\n" not in self.fp.read(100): 43 | raise SyntaxError("not an IM file") 44 | self.fp.seek(0) 45 | 46 | xsize = ysize = 0 47 | 48 | while True: 49 | 50 | s = self.fp.read(1) 51 | if not s: 52 | break 53 | 54 | if s == b"\x0C": 55 | 56 | # image data begins 57 | self.tile = [ 58 | ("raw", (0, 0) + self.size, self.fp.tell(), (self.mode, 0, 1)) 59 | ] 60 | 61 | break 62 | 63 | else: 64 | 65 | # read key/value pair 66 | # FIXME: dangerous, may read whole file 67 | s = s + self.fp.readline() 68 | if len(s) == 1 or len(s) > 100: 69 | break 70 | if s[0] == ord(b"*"): 71 | continue # comment 72 | 73 | m = field.match(s) 74 | if not m: 75 | break 76 | k, v = m.group(1, 2) 77 | if k == "width": 78 | xsize = int(v) 79 | self._size = xsize, ysize 80 | elif k == "height": 81 | ysize = int(v) 82 | self._size = xsize, ysize 83 | elif k == "pixel" and v == "n8": 84 | self.mode = "L" 85 | 86 | 87 | # 88 | # -------------------------------------------------------------------- 89 | 90 | Image.register_open(ImtImageFile.format, ImtImageFile) 91 | 92 | # 93 | # no extension registered (".im" is simply too common) 94 | -------------------------------------------------------------------------------- /.site-packages/PIL/McIdasImagePlugin.py: -------------------------------------------------------------------------------- 1 | # 2 | # The Python Imaging Library. 3 | # $Id$ 4 | # 5 | # Basic McIdas support for PIL 6 | # 7 | # History: 8 | # 1997-05-05 fl Created (8-bit images only) 9 | # 2009-03-08 fl Added 16/32-bit support. 10 | # 11 | # Thanks to Richard Jones and Craig Swank for specs and samples. 12 | # 13 | # Copyright (c) Secret Labs AB 1997. 14 | # Copyright (c) Fredrik Lundh 1997. 15 | # 16 | # See the README file for information on usage and redistribution. 17 | # 18 | 19 | import struct 20 | 21 | from . import Image, ImageFile 22 | 23 | 24 | def _accept(s): 25 | return s[:8] == b"\x00\x00\x00\x00\x00\x00\x00\x04" 26 | 27 | 28 | ## 29 | # Image plugin for McIdas area images. 30 | 31 | 32 | class McIdasImageFile(ImageFile.ImageFile): 33 | 34 | format = "MCIDAS" 35 | format_description = "McIdas area file" 36 | 37 | def _open(self): 38 | 39 | # parse area file directory 40 | s = self.fp.read(256) 41 | if not _accept(s) or len(s) != 256: 42 | raise SyntaxError("not an McIdas area file") 43 | 44 | self.area_descriptor_raw = s 45 | self.area_descriptor = w = [0] + list(struct.unpack("!64i", s)) 46 | 47 | # get mode 48 | if w[11] == 1: 49 | mode = rawmode = "L" 50 | elif w[11] == 2: 51 | # FIXME: add memory map support 52 | mode = "I" 53 | rawmode = "I;16B" 54 | elif w[11] == 4: 55 | # FIXME: add memory map support 56 | mode = "I" 57 | rawmode = "I;32B" 58 | else: 59 | raise SyntaxError("unsupported McIdas format") 60 | 61 | self.mode = mode 62 | self._size = w[10], w[9] 63 | 64 | offset = w[34] + w[15] 65 | stride = w[15] + w[10] * w[11] * w[14] 66 | 67 | self.tile = [("raw", (0, 0) + self.size, offset, (rawmode, stride, 1))] 68 | 69 | 70 | # -------------------------------------------------------------------- 71 | # registry 72 | 73 | Image.register_open(McIdasImageFile.format, McIdasImageFile, _accept) 74 | 75 | # no default extension 76 | -------------------------------------------------------------------------------- /.site-packages/PIL/MicImagePlugin.py: -------------------------------------------------------------------------------- 1 | # 2 | # The Python Imaging Library. 3 | # $Id$ 4 | # 5 | # Microsoft Image Composer support for PIL 6 | # 7 | # Notes: 8 | # uses TiffImagePlugin.py to read the actual image streams 9 | # 10 | # History: 11 | # 97-01-20 fl Created 12 | # 13 | # Copyright (c) Secret Labs AB 1997. 14 | # Copyright (c) Fredrik Lundh 1997. 15 | # 16 | # See the README file for information on usage and redistribution. 17 | # 18 | 19 | 20 | import olefile 21 | 22 | from . import Image, TiffImagePlugin 23 | 24 | # 25 | # -------------------------------------------------------------------- 26 | 27 | 28 | def _accept(prefix): 29 | return prefix[:8] == olefile.MAGIC 30 | 31 | 32 | ## 33 | # Image plugin for Microsoft's Image Composer file format. 34 | 35 | 36 | class MicImageFile(TiffImagePlugin.TiffImageFile): 37 | 38 | format = "MIC" 39 | format_description = "Microsoft Image Composer" 40 | _close_exclusive_fp_after_loading = False 41 | 42 | def _open(self): 43 | 44 | # read the OLE directory and see if this is a likely 45 | # to be a Microsoft Image Composer file 46 | 47 | try: 48 | self.ole = olefile.OleFileIO(self.fp) 49 | except OSError as e: 50 | raise SyntaxError("not an MIC file; invalid OLE file") from e 51 | 52 | # find ACI subfiles with Image members (maybe not the 53 | # best way to identify MIC files, but what the... ;-) 54 | 55 | self.images = [] 56 | for path in self.ole.listdir(): 57 | if path[1:] and path[0][-4:] == ".ACI" and path[1] == "Image": 58 | self.images.append(path) 59 | 60 | # if we didn't find any images, this is probably not 61 | # an MIC file. 62 | if not self.images: 63 | raise SyntaxError("not an MIC file; no image entries") 64 | 65 | self.__fp = self.fp 66 | self.frame = None 67 | self._n_frames = len(self.images) 68 | self.is_animated = self._n_frames > 1 69 | 70 | if len(self.images) > 1: 71 | self._category = Image.CONTAINER 72 | 73 | self.seek(0) 74 | 75 | def seek(self, frame): 76 | if not self._seek_check(frame): 77 | return 78 | try: 79 | filename = self.images[frame] 80 | except IndexError as e: 81 | raise EOFError("no such frame") from e 82 | 83 | self.fp = self.ole.openstream(filename) 84 | 85 | TiffImagePlugin.TiffImageFile._open(self) 86 | 87 | self.frame = frame 88 | 89 | def tell(self): 90 | return self.frame 91 | 92 | def _close__fp(self): 93 | try: 94 | if self.__fp != self.fp: 95 | self.__fp.close() 96 | except AttributeError: 97 | pass 98 | finally: 99 | self.__fp = None 100 | 101 | 102 | # 103 | # -------------------------------------------------------------------- 104 | 105 | Image.register_open(MicImageFile.format, MicImageFile, _accept) 106 | 107 | Image.register_extension(MicImageFile.format, ".mic") 108 | -------------------------------------------------------------------------------- /.site-packages/PIL/MpegImagePlugin.py: -------------------------------------------------------------------------------- 1 | # 2 | # The Python Imaging Library. 3 | # $Id$ 4 | # 5 | # MPEG file handling 6 | # 7 | # History: 8 | # 95-09-09 fl Created 9 | # 10 | # Copyright (c) Secret Labs AB 1997. 11 | # Copyright (c) Fredrik Lundh 1995. 12 | # 13 | # See the README file for information on usage and redistribution. 14 | # 15 | 16 | 17 | from . import Image, ImageFile 18 | from ._binary import i8 19 | 20 | # 21 | # Bitstream parser 22 | 23 | 24 | class BitStream: 25 | def __init__(self, fp): 26 | self.fp = fp 27 | self.bits = 0 28 | self.bitbuffer = 0 29 | 30 | def next(self): 31 | return i8(self.fp.read(1)) 32 | 33 | def peek(self, bits): 34 | while self.bits < bits: 35 | c = self.next() 36 | if c < 0: 37 | self.bits = 0 38 | continue 39 | self.bitbuffer = (self.bitbuffer << 8) + c 40 | self.bits += 8 41 | return self.bitbuffer >> (self.bits - bits) & (1 << bits) - 1 42 | 43 | def skip(self, bits): 44 | while self.bits < bits: 45 | self.bitbuffer = (self.bitbuffer << 8) + i8(self.fp.read(1)) 46 | self.bits += 8 47 | self.bits = self.bits - bits 48 | 49 | def read(self, bits): 50 | v = self.peek(bits) 51 | self.bits = self.bits - bits 52 | return v 53 | 54 | 55 | ## 56 | # Image plugin for MPEG streams. This plugin can identify a stream, 57 | # but it cannot read it. 58 | 59 | 60 | class MpegImageFile(ImageFile.ImageFile): 61 | 62 | format = "MPEG" 63 | format_description = "MPEG" 64 | 65 | def _open(self): 66 | 67 | s = BitStream(self.fp) 68 | 69 | if s.read(32) != 0x1B3: 70 | raise SyntaxError("not an MPEG file") 71 | 72 | self.mode = "RGB" 73 | self._size = s.read(12), s.read(12) 74 | 75 | 76 | # -------------------------------------------------------------------- 77 | # Registry stuff 78 | 79 | Image.register_open(MpegImageFile.format, MpegImageFile) 80 | 81 | Image.register_extensions(MpegImageFile.format, [".mpg", ".mpeg"]) 82 | 83 | Image.register_mime(MpegImageFile.format, "video/mpeg") 84 | -------------------------------------------------------------------------------- /.site-packages/PIL/MpoImagePlugin.py: -------------------------------------------------------------------------------- 1 | # 2 | # The Python Imaging Library. 3 | # $Id$ 4 | # 5 | # MPO file handling 6 | # 7 | # See "Multi-Picture Format" (CIPA DC-007-Translation 2009, Standard of the 8 | # Camera & Imaging Products Association) 9 | # 10 | # The multi-picture object combines multiple JPEG images (with a modified EXIF 11 | # data format) into a single file. While it can theoretically be used much like 12 | # a GIF animation, it is commonly used to represent 3D photographs and is (as 13 | # of this writing) the most commonly used format by 3D cameras. 14 | # 15 | # History: 16 | # 2014-03-13 Feneric Created 17 | # 18 | # See the README file for information on usage and redistribution. 19 | # 20 | 21 | from . import Image, ImageFile, JpegImagePlugin 22 | from ._binary import i16be as i16 23 | 24 | # def _accept(prefix): 25 | # return JpegImagePlugin._accept(prefix) 26 | 27 | 28 | def _save(im, fp, filename): 29 | # Note that we can only save the current frame at present 30 | return JpegImagePlugin._save(im, fp, filename) 31 | 32 | 33 | ## 34 | # Image plugin for MPO images. 35 | 36 | 37 | class MpoImageFile(JpegImagePlugin.JpegImageFile): 38 | 39 | format = "MPO" 40 | format_description = "MPO (CIPA DC-007)" 41 | _close_exclusive_fp_after_loading = False 42 | 43 | def _open(self): 44 | self.fp.seek(0) # prep the fp in order to pass the JPEG test 45 | JpegImagePlugin.JpegImageFile._open(self) 46 | self._after_jpeg_open() 47 | 48 | def _after_jpeg_open(self, mpheader=None): 49 | self._initial_size = self.size 50 | self.mpinfo = mpheader if mpheader is not None else self._getmp() 51 | self.n_frames = self.mpinfo[0xB001] 52 | self.__mpoffsets = [ 53 | mpent["DataOffset"] + self.info["mpoffset"] for mpent in self.mpinfo[0xB002] 54 | ] 55 | self.__mpoffsets[0] = 0 56 | # Note that the following assertion will only be invalid if something 57 | # gets broken within JpegImagePlugin. 58 | assert self.n_frames == len(self.__mpoffsets) 59 | del self.info["mpoffset"] # no longer needed 60 | self.is_animated = self.n_frames > 1 61 | self.__fp = self.fp # FIXME: hack 62 | self.__fp.seek(self.__mpoffsets[0]) # get ready to read first frame 63 | self.__frame = 0 64 | self.offset = 0 65 | # for now we can only handle reading and individual frame extraction 66 | self.readonly = 1 67 | 68 | def load_seek(self, pos): 69 | self.__fp.seek(pos) 70 | 71 | def seek(self, frame): 72 | if not self._seek_check(frame): 73 | return 74 | self.fp = self.__fp 75 | self.offset = self.__mpoffsets[frame] 76 | 77 | self.fp.seek(self.offset + 2) # skip SOI marker 78 | segment = self.fp.read(2) 79 | if not segment: 80 | raise ValueError("No data found for frame") 81 | self._size = self._initial_size 82 | if i16(segment) == 0xFFE1: # APP1 83 | n = i16(self.fp.read(2)) - 2 84 | self.info["exif"] = ImageFile._safe_read(self.fp, n) 85 | 86 | mptype = self.mpinfo[0xB002][frame]["Attribute"]["MPType"] 87 | if mptype.startswith("Large Thumbnail"): 88 | exif = self.getexif().get_ifd(0x8769) 89 | if 40962 in exif and 40963 in exif: 90 | self._size = (exif[40962], exif[40963]) 91 | elif "exif" in self.info: 92 | del self.info["exif"] 93 | 94 | self.tile = [("jpeg", (0, 0) + self.size, self.offset, (self.mode, ""))] 95 | self.__frame = frame 96 | 97 | def tell(self): 98 | return self.__frame 99 | 100 | def _close__fp(self): 101 | try: 102 | if self.__fp != self.fp: 103 | self.__fp.close() 104 | except AttributeError: 105 | pass 106 | finally: 107 | self.__fp = None 108 | 109 | @staticmethod 110 | def adopt(jpeg_instance, mpheader=None): 111 | """ 112 | Transform the instance of JpegImageFile into 113 | an instance of MpoImageFile. 114 | After the call, the JpegImageFile is extended 115 | to be an MpoImageFile. 116 | 117 | This is essentially useful when opening a JPEG 118 | file that reveals itself as an MPO, to avoid 119 | double call to _open. 120 | """ 121 | jpeg_instance.__class__ = MpoImageFile 122 | jpeg_instance._after_jpeg_open(mpheader) 123 | return jpeg_instance 124 | 125 | 126 | # --------------------------------------------------------------------- 127 | # Registry stuff 128 | 129 | # Note that since MPO shares a factory with JPEG, we do not need to do a 130 | # separate registration for it here. 131 | # Image.register_open(MpoImageFile.format, 132 | # JpegImagePlugin.jpeg_factory, _accept) 133 | Image.register_save(MpoImageFile.format, _save) 134 | 135 | Image.register_extension(MpoImageFile.format, ".mpo") 136 | 137 | Image.register_mime(MpoImageFile.format, "image/mpo") 138 | -------------------------------------------------------------------------------- /.site-packages/PIL/PaletteFile.py: -------------------------------------------------------------------------------- 1 | # 2 | # Python Imaging Library 3 | # $Id$ 4 | # 5 | # stuff to read simple, teragon-style palette files 6 | # 7 | # History: 8 | # 97-08-23 fl Created 9 | # 10 | # Copyright (c) Secret Labs AB 1997. 11 | # Copyright (c) Fredrik Lundh 1997. 12 | # 13 | # See the README file for information on usage and redistribution. 14 | # 15 | 16 | from ._binary import o8 17 | 18 | 19 | class PaletteFile: 20 | """File handler for Teragon-style palette files.""" 21 | 22 | rawmode = "RGB" 23 | 24 | def __init__(self, fp): 25 | 26 | self.palette = [(i, i, i) for i in range(256)] 27 | 28 | while True: 29 | 30 | s = fp.readline() 31 | 32 | if not s: 33 | break 34 | if s[0:1] == b"#": 35 | continue 36 | if len(s) > 100: 37 | raise SyntaxError("bad palette file") 38 | 39 | v = [int(x) for x in s.split()] 40 | try: 41 | [i, r, g, b] = v 42 | except ValueError: 43 | [i, r] = v 44 | g = b = r 45 | 46 | if 0 <= i <= 255: 47 | self.palette[i] = o8(r) + o8(g) + o8(b) 48 | 49 | self.palette = b"".join(self.palette) 50 | 51 | def getpalette(self): 52 | 53 | return self.palette, self.rawmode 54 | -------------------------------------------------------------------------------- /.site-packages/PIL/PcdImagePlugin.py: -------------------------------------------------------------------------------- 1 | # 2 | # The Python Imaging Library. 3 | # $Id$ 4 | # 5 | # PCD file handling 6 | # 7 | # History: 8 | # 96-05-10 fl Created 9 | # 96-05-27 fl Added draft mode (128x192, 256x384) 10 | # 11 | # Copyright (c) Secret Labs AB 1997. 12 | # Copyright (c) Fredrik Lundh 1996. 13 | # 14 | # See the README file for information on usage and redistribution. 15 | # 16 | 17 | 18 | from . import Image, ImageFile 19 | 20 | ## 21 | # Image plugin for PhotoCD images. This plugin only reads the 768x512 22 | # image from the file; higher resolutions are encoded in a proprietary 23 | # encoding. 24 | 25 | 26 | class PcdImageFile(ImageFile.ImageFile): 27 | 28 | format = "PCD" 29 | format_description = "Kodak PhotoCD" 30 | 31 | def _open(self): 32 | 33 | # rough 34 | self.fp.seek(2048) 35 | s = self.fp.read(2048) 36 | 37 | if s[:4] != b"PCD_": 38 | raise SyntaxError("not a PCD file") 39 | 40 | orientation = s[1538] & 3 41 | self.tile_post_rotate = None 42 | if orientation == 1: 43 | self.tile_post_rotate = 90 44 | elif orientation == 3: 45 | self.tile_post_rotate = -90 46 | 47 | self.mode = "RGB" 48 | self._size = 768, 512 # FIXME: not correct for rotated images! 49 | self.tile = [("pcd", (0, 0) + self.size, 96 * 2048, None)] 50 | 51 | def load_end(self): 52 | if self.tile_post_rotate: 53 | # Handle rotated PCDs 54 | self.im = self.im.rotate(self.tile_post_rotate) 55 | self._size = self.im.size 56 | 57 | 58 | # 59 | # registry 60 | 61 | Image.register_open(PcdImageFile.format, PcdImageFile) 62 | 63 | Image.register_extension(PcdImageFile.format, ".pcd") 64 | -------------------------------------------------------------------------------- /.site-packages/PIL/PixarImagePlugin.py: -------------------------------------------------------------------------------- 1 | # 2 | # The Python Imaging Library. 3 | # $Id$ 4 | # 5 | # PIXAR raster support for PIL 6 | # 7 | # history: 8 | # 97-01-29 fl Created 9 | # 10 | # notes: 11 | # This is incomplete; it is based on a few samples created with 12 | # Photoshop 2.5 and 3.0, and a summary description provided by 13 | # Greg Coats . Hopefully, "L" and 14 | # "RGBA" support will be added in future versions. 15 | # 16 | # Copyright (c) Secret Labs AB 1997. 17 | # Copyright (c) Fredrik Lundh 1997. 18 | # 19 | # See the README file for information on usage and redistribution. 20 | # 21 | 22 | from . import Image, ImageFile 23 | from ._binary import i16le as i16 24 | 25 | # 26 | # helpers 27 | 28 | 29 | def _accept(prefix): 30 | return prefix[:4] == b"\200\350\000\000" 31 | 32 | 33 | ## 34 | # Image plugin for PIXAR raster images. 35 | 36 | 37 | class PixarImageFile(ImageFile.ImageFile): 38 | 39 | format = "PIXAR" 40 | format_description = "PIXAR raster image" 41 | 42 | def _open(self): 43 | 44 | # assuming a 4-byte magic label 45 | s = self.fp.read(4) 46 | if not _accept(s): 47 | raise SyntaxError("not a PIXAR file") 48 | 49 | # read rest of header 50 | s = s + self.fp.read(508) 51 | 52 | self._size = i16(s, 418), i16(s, 416) 53 | 54 | # get channel/depth descriptions 55 | mode = i16(s, 424), i16(s, 426) 56 | 57 | if mode == (14, 2): 58 | self.mode = "RGB" 59 | # FIXME: to be continued... 60 | 61 | # create tile descriptor (assuming "dumped") 62 | self.tile = [("raw", (0, 0) + self.size, 1024, (self.mode, 0, 1))] 63 | 64 | 65 | # 66 | # -------------------------------------------------------------------- 67 | 68 | Image.register_open(PixarImageFile.format, PixarImageFile, _accept) 69 | 70 | Image.register_extension(PixarImageFile.format, ".pxr") 71 | -------------------------------------------------------------------------------- /.site-packages/PIL/SunImagePlugin.py: -------------------------------------------------------------------------------- 1 | # 2 | # The Python Imaging Library. 3 | # $Id$ 4 | # 5 | # Sun image file handling 6 | # 7 | # History: 8 | # 1995-09-10 fl Created 9 | # 1996-05-28 fl Fixed 32-bit alignment 10 | # 1998-12-29 fl Import ImagePalette module 11 | # 2001-12-18 fl Fixed palette loading (from Jean-Claude Rimbault) 12 | # 13 | # Copyright (c) 1997-2001 by Secret Labs AB 14 | # Copyright (c) 1995-1996 by Fredrik Lundh 15 | # 16 | # See the README file for information on usage and redistribution. 17 | # 18 | 19 | 20 | from . import Image, ImageFile, ImagePalette 21 | from ._binary import i32be as i32 22 | 23 | 24 | def _accept(prefix): 25 | return len(prefix) >= 4 and i32(prefix) == 0x59A66A95 26 | 27 | 28 | ## 29 | # Image plugin for Sun raster files. 30 | 31 | 32 | class SunImageFile(ImageFile.ImageFile): 33 | 34 | format = "SUN" 35 | format_description = "Sun Raster File" 36 | 37 | def _open(self): 38 | 39 | # The Sun Raster file header is 32 bytes in length 40 | # and has the following format: 41 | 42 | # typedef struct _SunRaster 43 | # { 44 | # DWORD MagicNumber; /* Magic (identification) number */ 45 | # DWORD Width; /* Width of image in pixels */ 46 | # DWORD Height; /* Height of image in pixels */ 47 | # DWORD Depth; /* Number of bits per pixel */ 48 | # DWORD Length; /* Size of image data in bytes */ 49 | # DWORD Type; /* Type of raster file */ 50 | # DWORD ColorMapType; /* Type of color map */ 51 | # DWORD ColorMapLength; /* Size of the color map in bytes */ 52 | # } SUNRASTER; 53 | 54 | # HEAD 55 | s = self.fp.read(32) 56 | if not _accept(s): 57 | raise SyntaxError("not an SUN raster file") 58 | 59 | offset = 32 60 | 61 | self._size = i32(s, 4), i32(s, 8) 62 | 63 | depth = i32(s, 12) 64 | # data_length = i32(s, 16) # unreliable, ignore. 65 | file_type = i32(s, 20) 66 | palette_type = i32(s, 24) # 0: None, 1: RGB, 2: Raw/arbitrary 67 | palette_length = i32(s, 28) 68 | 69 | if depth == 1: 70 | self.mode, rawmode = "1", "1;I" 71 | elif depth == 4: 72 | self.mode, rawmode = "L", "L;4" 73 | elif depth == 8: 74 | self.mode = rawmode = "L" 75 | elif depth == 24: 76 | if file_type == 3: 77 | self.mode, rawmode = "RGB", "RGB" 78 | else: 79 | self.mode, rawmode = "RGB", "BGR" 80 | elif depth == 32: 81 | if file_type == 3: 82 | self.mode, rawmode = "RGB", "RGBX" 83 | else: 84 | self.mode, rawmode = "RGB", "BGRX" 85 | else: 86 | raise SyntaxError("Unsupported Mode/Bit Depth") 87 | 88 | if palette_length: 89 | if palette_length > 1024: 90 | raise SyntaxError("Unsupported Color Palette Length") 91 | 92 | if palette_type != 1: 93 | raise SyntaxError("Unsupported Palette Type") 94 | 95 | offset = offset + palette_length 96 | self.palette = ImagePalette.raw("RGB;L", self.fp.read(palette_length)) 97 | if self.mode == "L": 98 | self.mode = "P" 99 | rawmode = rawmode.replace("L", "P") 100 | 101 | # 16 bit boundaries on stride 102 | stride = ((self.size[0] * depth + 15) // 16) * 2 103 | 104 | # file type: Type is the version (or flavor) of the bitmap 105 | # file. The following values are typically found in the Type 106 | # field: 107 | # 0000h Old 108 | # 0001h Standard 109 | # 0002h Byte-encoded 110 | # 0003h RGB format 111 | # 0004h TIFF format 112 | # 0005h IFF format 113 | # FFFFh Experimental 114 | 115 | # Old and standard are the same, except for the length tag. 116 | # byte-encoded is run-length-encoded 117 | # RGB looks similar to standard, but RGB byte order 118 | # TIFF and IFF mean that they were converted from T/IFF 119 | # Experimental means that it's something else. 120 | # (https://www.fileformat.info/format/sunraster/egff.htm) 121 | 122 | if file_type in (0, 1, 3, 4, 5): 123 | self.tile = [("raw", (0, 0) + self.size, offset, (rawmode, stride))] 124 | elif file_type == 2: 125 | self.tile = [("sun_rle", (0, 0) + self.size, offset, rawmode)] 126 | else: 127 | raise SyntaxError("Unsupported Sun Raster file type") 128 | 129 | 130 | # 131 | # registry 132 | 133 | 134 | Image.register_open(SunImageFile.format, SunImageFile, _accept) 135 | 136 | Image.register_extension(SunImageFile.format, ".ras") 137 | -------------------------------------------------------------------------------- /.site-packages/PIL/TarIO.py: -------------------------------------------------------------------------------- 1 | # 2 | # The Python Imaging Library. 3 | # $Id$ 4 | # 5 | # read files from within a tar file 6 | # 7 | # History: 8 | # 95-06-18 fl Created 9 | # 96-05-28 fl Open files in binary mode 10 | # 11 | # Copyright (c) Secret Labs AB 1997. 12 | # Copyright (c) Fredrik Lundh 1995-96. 13 | # 14 | # See the README file for information on usage and redistribution. 15 | # 16 | 17 | import io 18 | 19 | from . import ContainerIO 20 | 21 | 22 | class TarIO(ContainerIO.ContainerIO): 23 | """A file object that provides read access to a given member of a TAR file.""" 24 | 25 | def __init__(self, tarfile, file): 26 | """ 27 | Create file object. 28 | 29 | :param tarfile: Name of TAR file. 30 | :param file: Name of member file. 31 | """ 32 | self.fh = open(tarfile, "rb") 33 | 34 | while True: 35 | 36 | s = self.fh.read(512) 37 | if len(s) != 512: 38 | raise OSError("unexpected end of tar file") 39 | 40 | name = s[:100].decode("utf-8") 41 | i = name.find("\0") 42 | if i == 0: 43 | raise OSError("cannot find subfile") 44 | if i > 0: 45 | name = name[:i] 46 | 47 | size = int(s[124:135], 8) 48 | 49 | if file == name: 50 | break 51 | 52 | self.fh.seek((size + 511) & (~511), io.SEEK_CUR) 53 | 54 | # Open region 55 | super().__init__(self.fh, self.fh.tell(), size) 56 | 57 | # Context manager support 58 | def __enter__(self): 59 | return self 60 | 61 | def __exit__(self, *args): 62 | self.close() 63 | 64 | def close(self): 65 | self.fh.close() 66 | -------------------------------------------------------------------------------- /.site-packages/PIL/WmfImagePlugin.py: -------------------------------------------------------------------------------- 1 | # 2 | # The Python Imaging Library 3 | # $Id$ 4 | # 5 | # WMF stub codec 6 | # 7 | # history: 8 | # 1996-12-14 fl Created 9 | # 2004-02-22 fl Turned into a stub driver 10 | # 2004-02-23 fl Added EMF support 11 | # 12 | # Copyright (c) Secret Labs AB 1997-2004. All rights reserved. 13 | # Copyright (c) Fredrik Lundh 1996. 14 | # 15 | # See the README file for information on usage and redistribution. 16 | # 17 | # WMF/EMF reference documentation: 18 | # https://winprotocoldoc.blob.core.windows.net/productionwindowsarchives/MS-WMF/[MS-WMF].pdf 19 | # http://wvware.sourceforge.net/caolan/index.html 20 | # http://wvware.sourceforge.net/caolan/ora-wmf.html 21 | 22 | from . import Image, ImageFile 23 | from ._binary import i16le as word 24 | from ._binary import si16le as short 25 | from ._binary import si32le as _long 26 | 27 | _handler = None 28 | 29 | 30 | def register_handler(handler): 31 | """ 32 | Install application-specific WMF image handler. 33 | 34 | :param handler: Handler object. 35 | """ 36 | global _handler 37 | _handler = handler 38 | 39 | 40 | if hasattr(Image.core, "drawwmf"): 41 | # install default handler (windows only) 42 | 43 | class WmfHandler: 44 | def open(self, im): 45 | im.mode = "RGB" 46 | self.bbox = im.info["wmf_bbox"] 47 | 48 | def load(self, im): 49 | im.fp.seek(0) # rewind 50 | return Image.frombytes( 51 | "RGB", 52 | im.size, 53 | Image.core.drawwmf(im.fp.read(), im.size, self.bbox), 54 | "raw", 55 | "BGR", 56 | (im.size[0] * 3 + 3) & -4, 57 | -1, 58 | ) 59 | 60 | register_handler(WmfHandler()) 61 | 62 | # 63 | # -------------------------------------------------------------------- 64 | # Read WMF file 65 | 66 | 67 | def _accept(prefix): 68 | return ( 69 | prefix[:6] == b"\xd7\xcd\xc6\x9a\x00\x00" or prefix[:4] == b"\x01\x00\x00\x00" 70 | ) 71 | 72 | 73 | ## 74 | # Image plugin for Windows metafiles. 75 | 76 | 77 | class WmfStubImageFile(ImageFile.StubImageFile): 78 | 79 | format = "WMF" 80 | format_description = "Windows Metafile" 81 | 82 | def _open(self): 83 | self._inch = None 84 | 85 | # check placable header 86 | s = self.fp.read(80) 87 | 88 | if s[:6] == b"\xd7\xcd\xc6\x9a\x00\x00": 89 | 90 | # placeable windows metafile 91 | 92 | # get units per inch 93 | self._inch = word(s, 14) 94 | 95 | # get bounding box 96 | x0 = short(s, 6) 97 | y0 = short(s, 8) 98 | x1 = short(s, 10) 99 | y1 = short(s, 12) 100 | 101 | # normalize size to 72 dots per inch 102 | self.info["dpi"] = 72 103 | size = ( 104 | (x1 - x0) * self.info["dpi"] // self._inch, 105 | (y1 - y0) * self.info["dpi"] // self._inch, 106 | ) 107 | 108 | self.info["wmf_bbox"] = x0, y0, x1, y1 109 | 110 | # sanity check (standard metafile header) 111 | if s[22:26] != b"\x01\x00\t\x00": 112 | raise SyntaxError("Unsupported WMF file format") 113 | 114 | elif s[:4] == b"\x01\x00\x00\x00" and s[40:44] == b" EMF": 115 | # enhanced metafile 116 | 117 | # get bounding box 118 | x0 = _long(s, 8) 119 | y0 = _long(s, 12) 120 | x1 = _long(s, 16) 121 | y1 = _long(s, 20) 122 | 123 | # get frame (in 0.01 millimeter units) 124 | frame = _long(s, 24), _long(s, 28), _long(s, 32), _long(s, 36) 125 | 126 | size = x1 - x0, y1 - y0 127 | 128 | # calculate dots per inch from bbox and frame 129 | xdpi = 2540.0 * (x1 - y0) / (frame[2] - frame[0]) 130 | ydpi = 2540.0 * (y1 - y0) / (frame[3] - frame[1]) 131 | 132 | self.info["wmf_bbox"] = x0, y0, x1, y1 133 | 134 | if xdpi == ydpi: 135 | self.info["dpi"] = xdpi 136 | else: 137 | self.info["dpi"] = xdpi, ydpi 138 | 139 | else: 140 | raise SyntaxError("Unsupported file format") 141 | 142 | self.mode = "RGB" 143 | self._size = size 144 | 145 | loader = self._load() 146 | if loader: 147 | loader.open(self) 148 | 149 | def _load(self): 150 | return _handler 151 | 152 | def load(self, dpi=None): 153 | if dpi is not None and self._inch is not None: 154 | self.info["dpi"] = dpi 155 | x0, y0, x1, y1 = self.info["wmf_bbox"] 156 | self._size = ( 157 | (x1 - x0) * self.info["dpi"] // self._inch, 158 | (y1 - y0) * self.info["dpi"] // self._inch, 159 | ) 160 | return super().load() 161 | 162 | 163 | def _save(im, fp, filename): 164 | if _handler is None or not hasattr(_handler, "save"): 165 | raise OSError("WMF save handler not installed") 166 | _handler.save(im, fp, filename) 167 | 168 | 169 | # 170 | # -------------------------------------------------------------------- 171 | # Registry stuff 172 | 173 | 174 | Image.register_open(WmfStubImageFile.format, WmfStubImageFile, _accept) 175 | Image.register_save(WmfStubImageFile.format, _save) 176 | 177 | Image.register_extensions(WmfStubImageFile.format, [".wmf", ".emf"]) 178 | -------------------------------------------------------------------------------- /.site-packages/PIL/XVThumbImagePlugin.py: -------------------------------------------------------------------------------- 1 | # 2 | # The Python Imaging Library. 3 | # $Id$ 4 | # 5 | # XV Thumbnail file handler by Charles E. "Gene" Cash 6 | # (gcash@magicnet.net) 7 | # 8 | # see xvcolor.c and xvbrowse.c in the sources to John Bradley's XV, 9 | # available from ftp://ftp.cis.upenn.edu/pub/xv/ 10 | # 11 | # history: 12 | # 98-08-15 cec created (b/w only) 13 | # 98-12-09 cec added color palette 14 | # 98-12-28 fl added to PIL (with only a few very minor modifications) 15 | # 16 | # To do: 17 | # FIXME: make save work (this requires quantization support) 18 | # 19 | 20 | from . import Image, ImageFile, ImagePalette 21 | from ._binary import o8 22 | 23 | _MAGIC = b"P7 332" 24 | 25 | # standard color palette for thumbnails (RGB332) 26 | PALETTE = b"" 27 | for r in range(8): 28 | for g in range(8): 29 | for b in range(4): 30 | PALETTE = PALETTE + ( 31 | o8((r * 255) // 7) + o8((g * 255) // 7) + o8((b * 255) // 3) 32 | ) 33 | 34 | 35 | def _accept(prefix): 36 | return prefix[:6] == _MAGIC 37 | 38 | 39 | ## 40 | # Image plugin for XV thumbnail images. 41 | 42 | 43 | class XVThumbImageFile(ImageFile.ImageFile): 44 | 45 | format = "XVThumb" 46 | format_description = "XV thumbnail image" 47 | 48 | def _open(self): 49 | 50 | # check magic 51 | if not _accept(self.fp.read(6)): 52 | raise SyntaxError("not an XV thumbnail file") 53 | 54 | # Skip to beginning of next line 55 | self.fp.readline() 56 | 57 | # skip info comments 58 | while True: 59 | s = self.fp.readline() 60 | if not s: 61 | raise SyntaxError("Unexpected EOF reading XV thumbnail file") 62 | if s[0] != 35: # ie. when not a comment: '#' 63 | break 64 | 65 | # parse header line (already read) 66 | s = s.strip().split() 67 | 68 | self.mode = "P" 69 | self._size = int(s[0]), int(s[1]) 70 | 71 | self.palette = ImagePalette.raw("RGB", PALETTE) 72 | 73 | self.tile = [("raw", (0, 0) + self.size, self.fp.tell(), (self.mode, 0, 1))] 74 | 75 | 76 | # -------------------------------------------------------------------- 77 | 78 | Image.register_open(XVThumbImageFile.format, XVThumbImageFile, _accept) 79 | -------------------------------------------------------------------------------- /.site-packages/PIL/XbmImagePlugin.py: -------------------------------------------------------------------------------- 1 | # 2 | # The Python Imaging Library. 3 | # $Id$ 4 | # 5 | # XBM File handling 6 | # 7 | # History: 8 | # 1995-09-08 fl Created 9 | # 1996-11-01 fl Added save support 10 | # 1997-07-07 fl Made header parser more tolerant 11 | # 1997-07-22 fl Fixed yet another parser bug 12 | # 2001-02-17 fl Use 're' instead of 'regex' (Python 2.1) (0.4) 13 | # 2001-05-13 fl Added hotspot handling (based on code from Bernhard Herzog) 14 | # 2004-02-24 fl Allow some whitespace before first #define 15 | # 16 | # Copyright (c) 1997-2004 by Secret Labs AB 17 | # Copyright (c) 1996-1997 by Fredrik Lundh 18 | # 19 | # See the README file for information on usage and redistribution. 20 | # 21 | 22 | import re 23 | 24 | from . import Image, ImageFile 25 | 26 | # XBM header 27 | xbm_head = re.compile( 28 | rb"\s*#define[ \t]+.*_width[ \t]+(?P[0-9]+)[\r\n]+" 29 | b"#define[ \t]+.*_height[ \t]+(?P[0-9]+)[\r\n]+" 30 | b"(?P" 31 | b"#define[ \t]+[^_]*_x_hot[ \t]+(?P[0-9]+)[\r\n]+" 32 | b"#define[ \t]+[^_]*_y_hot[ \t]+(?P[0-9]+)[\r\n]+" 33 | b")?" 34 | b"[\\000-\\377]*_bits\\[\\]" 35 | ) 36 | 37 | 38 | def _accept(prefix): 39 | return prefix.lstrip()[:7] == b"#define" 40 | 41 | 42 | ## 43 | # Image plugin for X11 bitmaps. 44 | 45 | 46 | class XbmImageFile(ImageFile.ImageFile): 47 | 48 | format = "XBM" 49 | format_description = "X11 Bitmap" 50 | 51 | def _open(self): 52 | 53 | m = xbm_head.match(self.fp.read(512)) 54 | 55 | if not m: 56 | raise SyntaxError("not a XBM file") 57 | 58 | xsize = int(m.group("width")) 59 | ysize = int(m.group("height")) 60 | 61 | if m.group("hotspot"): 62 | self.info["hotspot"] = (int(m.group("xhot")), int(m.group("yhot"))) 63 | 64 | self.mode = "1" 65 | self._size = xsize, ysize 66 | 67 | self.tile = [("xbm", (0, 0) + self.size, m.end(), None)] 68 | 69 | 70 | def _save(im, fp, filename): 71 | 72 | if im.mode != "1": 73 | raise OSError(f"cannot write mode {im.mode} as XBM") 74 | 75 | fp.write(f"#define im_width {im.size[0]}\n".encode("ascii")) 76 | fp.write(f"#define im_height {im.size[1]}\n".encode("ascii")) 77 | 78 | hotspot = im.encoderinfo.get("hotspot") 79 | if hotspot: 80 | fp.write(f"#define im_x_hot {hotspot[0]}\n".encode("ascii")) 81 | fp.write(f"#define im_y_hot {hotspot[1]}\n".encode("ascii")) 82 | 83 | fp.write(b"static char im_bits[] = {\n") 84 | 85 | ImageFile._save(im, fp, [("xbm", (0, 0) + im.size, 0, None)]) 86 | 87 | fp.write(b"};\n") 88 | 89 | 90 | Image.register_open(XbmImageFile.format, XbmImageFile, _accept) 91 | Image.register_save(XbmImageFile.format, _save) 92 | 93 | Image.register_extension(XbmImageFile.format, ".xbm") 94 | 95 | Image.register_mime(XbmImageFile.format, "image/xbm") 96 | -------------------------------------------------------------------------------- /.site-packages/PIL/XpmImagePlugin.py: -------------------------------------------------------------------------------- 1 | # 2 | # The Python Imaging Library. 3 | # $Id$ 4 | # 5 | # XPM File handling 6 | # 7 | # History: 8 | # 1996-12-29 fl Created 9 | # 2001-02-17 fl Use 're' instead of 'regex' (Python 2.1) (0.7) 10 | # 11 | # Copyright (c) Secret Labs AB 1997-2001. 12 | # Copyright (c) Fredrik Lundh 1996-2001. 13 | # 14 | # See the README file for information on usage and redistribution. 15 | # 16 | 17 | 18 | import re 19 | 20 | from . import Image, ImageFile, ImagePalette 21 | from ._binary import o8 22 | 23 | # XPM header 24 | xpm_head = re.compile(b'"([0-9]*) ([0-9]*) ([0-9]*) ([0-9]*)') 25 | 26 | 27 | def _accept(prefix): 28 | return prefix[:9] == b"/* XPM */" 29 | 30 | 31 | ## 32 | # Image plugin for X11 pixel maps. 33 | 34 | 35 | class XpmImageFile(ImageFile.ImageFile): 36 | 37 | format = "XPM" 38 | format_description = "X11 Pixel Map" 39 | 40 | def _open(self): 41 | 42 | if not _accept(self.fp.read(9)): 43 | raise SyntaxError("not an XPM file") 44 | 45 | # skip forward to next string 46 | while True: 47 | s = self.fp.readline() 48 | if not s: 49 | raise SyntaxError("broken XPM file") 50 | m = xpm_head.match(s) 51 | if m: 52 | break 53 | 54 | self._size = int(m.group(1)), int(m.group(2)) 55 | 56 | pal = int(m.group(3)) 57 | bpp = int(m.group(4)) 58 | 59 | if pal > 256 or bpp != 1: 60 | raise ValueError("cannot read this XPM file") 61 | 62 | # 63 | # load palette description 64 | 65 | palette = [b"\0\0\0"] * 256 66 | 67 | for i in range(pal): 68 | 69 | s = self.fp.readline() 70 | if s[-2:] == b"\r\n": 71 | s = s[:-2] 72 | elif s[-1:] in b"\r\n": 73 | s = s[:-1] 74 | 75 | c = s[1] 76 | s = s[2:-2].split() 77 | 78 | for i in range(0, len(s), 2): 79 | 80 | if s[i] == b"c": 81 | 82 | # process colour key 83 | rgb = s[i + 1] 84 | if rgb == b"None": 85 | self.info["transparency"] = c 86 | elif rgb[0:1] == b"#": 87 | # FIXME: handle colour names (see ImagePalette.py) 88 | rgb = int(rgb[1:], 16) 89 | palette[c] = ( 90 | o8((rgb >> 16) & 255) + o8((rgb >> 8) & 255) + o8(rgb & 255) 91 | ) 92 | else: 93 | # unknown colour 94 | raise ValueError("cannot read this XPM file") 95 | break 96 | 97 | else: 98 | 99 | # missing colour key 100 | raise ValueError("cannot read this XPM file") 101 | 102 | self.mode = "P" 103 | self.palette = ImagePalette.raw("RGB", b"".join(palette)) 104 | 105 | self.tile = [("raw", (0, 0) + self.size, self.fp.tell(), ("P", 0, 1))] 106 | 107 | def load_read(self, bytes): 108 | 109 | # 110 | # load all image data in one chunk 111 | 112 | xsize, ysize = self.size 113 | 114 | s = [None] * ysize 115 | 116 | for i in range(ysize): 117 | s[i] = self.fp.readline()[1 : xsize + 1].ljust(xsize) 118 | 119 | return b"".join(s) 120 | 121 | 122 | # 123 | # Registry 124 | 125 | 126 | Image.register_open(XpmImageFile.format, XpmImageFile, _accept) 127 | 128 | Image.register_extension(XpmImageFile.format, ".xpm") 129 | 130 | Image.register_mime(XpmImageFile.format, "image/xpm") 131 | -------------------------------------------------------------------------------- /.site-packages/PIL/__init__.py: -------------------------------------------------------------------------------- 1 | """Pillow (Fork of the Python Imaging Library) 2 | 3 | Pillow is the friendly PIL fork by Alex Clark and Contributors. 4 | https://github.com/python-pillow/Pillow/ 5 | 6 | Pillow is forked from PIL 1.1.7. 7 | 8 | PIL is the Python Imaging Library by Fredrik Lundh and Contributors. 9 | Copyright (c) 1999 by Secret Labs AB. 10 | 11 | Use PIL.__version__ for this Pillow version. 12 | 13 | ;-) 14 | """ 15 | 16 | from . import _version 17 | 18 | # VERSION was removed in Pillow 6.0.0. 19 | # PILLOW_VERSION was removed in Pillow 9.0.0. 20 | # Use __version__ instead. 21 | __version__ = _version.__version__ 22 | del _version 23 | 24 | 25 | _plugins = [ 26 | "BlpImagePlugin", 27 | "BmpImagePlugin", 28 | "BufrStubImagePlugin", 29 | "CurImagePlugin", 30 | "DcxImagePlugin", 31 | "DdsImagePlugin", 32 | "EpsImagePlugin", 33 | "FitsImagePlugin", 34 | "FitsStubImagePlugin", 35 | "FliImagePlugin", 36 | "FpxImagePlugin", 37 | "FtexImagePlugin", 38 | "GbrImagePlugin", 39 | "GifImagePlugin", 40 | "GribStubImagePlugin", 41 | "Hdf5StubImagePlugin", 42 | "IcnsImagePlugin", 43 | "IcoImagePlugin", 44 | "ImImagePlugin", 45 | "ImtImagePlugin", 46 | "IptcImagePlugin", 47 | "JpegImagePlugin", 48 | "Jpeg2KImagePlugin", 49 | "McIdasImagePlugin", 50 | "MicImagePlugin", 51 | "MpegImagePlugin", 52 | "MpoImagePlugin", 53 | "MspImagePlugin", 54 | "PalmImagePlugin", 55 | "PcdImagePlugin", 56 | "PcxImagePlugin", 57 | "PdfImagePlugin", 58 | "PixarImagePlugin", 59 | "PngImagePlugin", 60 | "PpmImagePlugin", 61 | "PsdImagePlugin", 62 | "SgiImagePlugin", 63 | "SpiderImagePlugin", 64 | "SunImagePlugin", 65 | "TgaImagePlugin", 66 | "TiffImagePlugin", 67 | "WebPImagePlugin", 68 | "WmfImagePlugin", 69 | "XbmImagePlugin", 70 | "XpmImagePlugin", 71 | "XVThumbImagePlugin", 72 | ] 73 | 74 | 75 | class UnidentifiedImageError(OSError): 76 | """ 77 | Raised in :py:meth:`PIL.Image.open` if an image cannot be opened and identified. 78 | """ 79 | 80 | pass 81 | -------------------------------------------------------------------------------- /.site-packages/PIL/__main__.py: -------------------------------------------------------------------------------- 1 | from .features import pilinfo 2 | 3 | pilinfo() 4 | -------------------------------------------------------------------------------- /.site-packages/PIL/_binary.py: -------------------------------------------------------------------------------- 1 | # 2 | # The Python Imaging Library. 3 | # $Id$ 4 | # 5 | # Binary input/output support routines. 6 | # 7 | # Copyright (c) 1997-2003 by Secret Labs AB 8 | # Copyright (c) 1995-2003 by Fredrik Lundh 9 | # Copyright (c) 2012 by Brian Crowell 10 | # 11 | # See the README file for information on usage and redistribution. 12 | # 13 | 14 | 15 | """Binary input/output support routines.""" 16 | 17 | 18 | from struct import pack, unpack_from 19 | 20 | 21 | def i8(c): 22 | return c if c.__class__ is int else c[0] 23 | 24 | 25 | def o8(i): 26 | return bytes((i & 255,)) 27 | 28 | 29 | # Input, le = little endian, be = big endian 30 | def i16le(c, o=0): 31 | """ 32 | Converts a 2-bytes (16 bits) string to an unsigned integer. 33 | 34 | :param c: string containing bytes to convert 35 | :param o: offset of bytes to convert in string 36 | """ 37 | return unpack_from("h", c, o)[0] 58 | 59 | 60 | def i32le(c, o=0): 61 | """ 62 | Converts a 4-bytes (32 bits) string to an unsigned integer. 63 | 64 | :param c: string containing bytes to convert 65 | :param o: offset of bytes to convert in string 66 | """ 67 | return unpack_from("H", c, o)[0] 82 | 83 | 84 | def i32be(c, o=0): 85 | return unpack_from(">I", c, o)[0] 86 | 87 | 88 | # Output, le = little endian, be = big endian 89 | def o16le(i): 90 | return pack("H", i) 99 | 100 | 101 | def o32be(i): 102 | return pack(">I", i) 103 | -------------------------------------------------------------------------------- /.site-packages/PIL/_tkinter_finder.py: -------------------------------------------------------------------------------- 1 | """ Find compiled module linking to Tcl / Tk libraries 2 | """ 3 | import sys 4 | import tkinter 5 | import warnings 6 | from tkinter import _tkinter as tk 7 | 8 | try: 9 | if hasattr(sys, "pypy_find_executable"): 10 | TKINTER_LIB = tk.tklib_cffi.__file__ 11 | else: 12 | TKINTER_LIB = tk.__file__ 13 | except AttributeError: 14 | # _tkinter may be compiled directly into Python, in which case __file__ is 15 | # not available. load_tkinter_funcs will check the binary first in any case. 16 | TKINTER_LIB = None 17 | 18 | tk_version = str(tkinter.TkVersion) 19 | if tk_version == "8.4": 20 | warnings.warn( 21 | "Support for Tk/Tcl 8.4 is deprecated and will be removed" 22 | " in Pillow 10 (2023-07-01). Please upgrade to Tk/Tcl 8.5 " 23 | "or newer.", 24 | DeprecationWarning, 25 | ) 26 | -------------------------------------------------------------------------------- /.site-packages/PIL/_util.py: -------------------------------------------------------------------------------- 1 | import os 2 | from pathlib import Path 3 | 4 | 5 | def isPath(f): 6 | return isinstance(f, (bytes, str, Path)) 7 | 8 | 9 | # Checks if an object is a string, and that it points to a directory. 10 | def isDirectory(f): 11 | return isPath(f) and os.path.isdir(f) 12 | 13 | 14 | class deferred_error: 15 | def __init__(self, ex): 16 | self.ex = ex 17 | 18 | def __getattr__(self, elt): 19 | raise self.ex 20 | -------------------------------------------------------------------------------- /.site-packages/PIL/_version.py: -------------------------------------------------------------------------------- 1 | # Master version for Pillow 2 | __version__ = "9.1.0" 3 | -------------------------------------------------------------------------------- /.site-packages/bin/normalizer: -------------------------------------------------------------------------------- 1 | #!/Library/Developer/CommandLineTools/usr/bin/python3 2 | # -*- coding: utf-8 -*- 3 | import re 4 | import sys 5 | from charset_normalizer.cli.normalizer import cli_detect 6 | if __name__ == '__main__': 7 | sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) 8 | sys.exit(cli_detect()) 9 | -------------------------------------------------------------------------------- /.site-packages/certifi/__init__.py: -------------------------------------------------------------------------------- 1 | from .core import contents, where 2 | 3 | __version__ = "2021.10.08" 4 | -------------------------------------------------------------------------------- /.site-packages/certifi/__main__.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | 3 | from certifi import contents, where 4 | 5 | parser = argparse.ArgumentParser() 6 | parser.add_argument("-c", "--contents", action="store_true") 7 | args = parser.parse_args() 8 | 9 | if args.contents: 10 | print(contents()) 11 | else: 12 | print(where()) 13 | -------------------------------------------------------------------------------- /.site-packages/certifi/core.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | """ 4 | certifi.py 5 | ~~~~~~~~~~ 6 | 7 | This module returns the installation location of cacert.pem or its contents. 8 | """ 9 | import os 10 | 11 | try: 12 | from importlib.resources import path as get_path, read_text 13 | 14 | _CACERT_CTX = None 15 | _CACERT_PATH = None 16 | 17 | def where(): 18 | # This is slightly terrible, but we want to delay extracting the file 19 | # in cases where we're inside of a zipimport situation until someone 20 | # actually calls where(), but we don't want to re-extract the file 21 | # on every call of where(), so we'll do it once then store it in a 22 | # global variable. 23 | global _CACERT_CTX 24 | global _CACERT_PATH 25 | if _CACERT_PATH is None: 26 | # This is slightly janky, the importlib.resources API wants you to 27 | # manage the cleanup of this file, so it doesn't actually return a 28 | # path, it returns a context manager that will give you the path 29 | # when you enter it and will do any cleanup when you leave it. In 30 | # the common case of not needing a temporary file, it will just 31 | # return the file system location and the __exit__() is a no-op. 32 | # 33 | # We also have to hold onto the actual context manager, because 34 | # it will do the cleanup whenever it gets garbage collected, so 35 | # we will also store that at the global level as well. 36 | _CACERT_CTX = get_path("certifi", "cacert.pem") 37 | _CACERT_PATH = str(_CACERT_CTX.__enter__()) 38 | 39 | return _CACERT_PATH 40 | 41 | 42 | except ImportError: 43 | # This fallback will work for Python versions prior to 3.7 that lack the 44 | # importlib.resources module but relies on the existing `where` function 45 | # so won't address issues with environments like PyOxidizer that don't set 46 | # __file__ on modules. 47 | def read_text(_module, _path, encoding="ascii"): 48 | with open(where(), "r", encoding=encoding) as data: 49 | return data.read() 50 | 51 | # If we don't have importlib.resources, then we will just do the old logic 52 | # of assuming we're on the filesystem and munge the path directly. 53 | def where(): 54 | f = os.path.dirname(__file__) 55 | 56 | return os.path.join(f, "cacert.pem") 57 | 58 | 59 | def contents(): 60 | return read_text("certifi", "cacert.pem", encoding="ascii") 61 | -------------------------------------------------------------------------------- /.site-packages/charset_normalizer/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf_8 -*- 2 | """ 3 | Charset-Normalizer 4 | ~~~~~~~~~~~~~~ 5 | The Real First Universal Charset Detector. 6 | A library that helps you read text from an unknown charset encoding. 7 | Motivated by chardet, This package is trying to resolve the issue by taking a new approach. 8 | All IANA character set names for which the Python core library provides codecs are supported. 9 | 10 | Basic usage: 11 | >>> from charset_normalizer import from_bytes 12 | >>> results = from_bytes('Bсеки човек има право на образование. Oбразованието!'.encode('utf_8')) 13 | >>> best_guess = results.best() 14 | >>> str(best_guess) 15 | 'Bсеки човек има право на образование. Oбразованието!' 16 | 17 | Others methods and usages are available - see the full documentation 18 | at . 19 | :copyright: (c) 2021 by Ahmed TAHRI 20 | :license: MIT, see LICENSE for more details. 21 | """ 22 | import logging 23 | 24 | from .api import from_bytes, from_fp, from_path, normalize 25 | from .legacy import ( 26 | CharsetDetector, 27 | CharsetDoctor, 28 | CharsetNormalizerMatch, 29 | CharsetNormalizerMatches, 30 | detect, 31 | ) 32 | from .models import CharsetMatch, CharsetMatches 33 | from .utils import set_logging_handler 34 | from .version import VERSION, __version__ 35 | 36 | __all__ = ( 37 | "from_fp", 38 | "from_path", 39 | "from_bytes", 40 | "normalize", 41 | "detect", 42 | "CharsetMatch", 43 | "CharsetMatches", 44 | "CharsetNormalizerMatch", 45 | "CharsetNormalizerMatches", 46 | "CharsetDetector", 47 | "CharsetDoctor", 48 | "__version__", 49 | "VERSION", 50 | "set_logging_handler", 51 | ) 52 | 53 | # Attach a NullHandler to the top level logger by default 54 | # https://docs.python.org/3.3/howto/logging.html#configuring-logging-for-a-library 55 | 56 | logging.getLogger("charset_normalizer").addHandler(logging.NullHandler()) 57 | -------------------------------------------------------------------------------- /.site-packages/charset_normalizer/cli/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jessedobbelaere/alfred-iterm-profiles-workflow/b6b44e42b1a9c9dff6b4b4fccadcbea1210b6eea/.site-packages/charset_normalizer/cli/__init__.py -------------------------------------------------------------------------------- /.site-packages/charset_normalizer/legacy.py: -------------------------------------------------------------------------------- 1 | import warnings 2 | from typing import Dict, Optional, Union 3 | 4 | from .api import from_bytes, from_fp, from_path, normalize 5 | from .constant import CHARDET_CORRESPONDENCE 6 | from .models import CharsetMatch, CharsetMatches 7 | 8 | 9 | def detect(byte_str: bytes) -> Dict[str, Optional[Union[str, float]]]: 10 | """ 11 | chardet legacy method 12 | Detect the encoding of the given byte string. It should be mostly backward-compatible. 13 | Encoding name will match Chardet own writing whenever possible. (Not on encoding name unsupported by it) 14 | This function is deprecated and should be used to migrate your project easily, consult the documentation for 15 | further information. Not planned for removal. 16 | 17 | :param byte_str: The byte sequence to examine. 18 | """ 19 | if not isinstance(byte_str, (bytearray, bytes)): 20 | raise TypeError( # pragma: nocover 21 | "Expected object of type bytes or bytearray, got: " 22 | "{0}".format(type(byte_str)) 23 | ) 24 | 25 | if isinstance(byte_str, bytearray): 26 | byte_str = bytes(byte_str) 27 | 28 | r = from_bytes(byte_str).best() 29 | 30 | encoding = r.encoding if r is not None else None 31 | language = r.language if r is not None and r.language != "Unknown" else "" 32 | confidence = 1.0 - r.chaos if r is not None else None 33 | 34 | # Note: CharsetNormalizer does not return 'UTF-8-SIG' as the sig get stripped in the detection/normalization process 35 | # but chardet does return 'utf-8-sig' and it is a valid codec name. 36 | if r is not None and encoding == "utf_8" and r.bom: 37 | encoding += "_sig" 38 | 39 | return { 40 | "encoding": encoding 41 | if encoding not in CHARDET_CORRESPONDENCE 42 | else CHARDET_CORRESPONDENCE[encoding], 43 | "language": language, 44 | "confidence": confidence, 45 | } 46 | 47 | 48 | class CharsetNormalizerMatch(CharsetMatch): 49 | pass 50 | 51 | 52 | class CharsetNormalizerMatches(CharsetMatches): 53 | @staticmethod 54 | def from_fp(*args, **kwargs): # type: ignore 55 | warnings.warn( # pragma: nocover 56 | "staticmethod from_fp, from_bytes, from_path and normalize are deprecated " 57 | "and scheduled to be removed in 3.0", 58 | DeprecationWarning, 59 | ) 60 | return from_fp(*args, **kwargs) # pragma: nocover 61 | 62 | @staticmethod 63 | def from_bytes(*args, **kwargs): # type: ignore 64 | warnings.warn( # pragma: nocover 65 | "staticmethod from_fp, from_bytes, from_path and normalize are deprecated " 66 | "and scheduled to be removed in 3.0", 67 | DeprecationWarning, 68 | ) 69 | return from_bytes(*args, **kwargs) # pragma: nocover 70 | 71 | @staticmethod 72 | def from_path(*args, **kwargs): # type: ignore 73 | warnings.warn( # pragma: nocover 74 | "staticmethod from_fp, from_bytes, from_path and normalize are deprecated " 75 | "and scheduled to be removed in 3.0", 76 | DeprecationWarning, 77 | ) 78 | return from_path(*args, **kwargs) # pragma: nocover 79 | 80 | @staticmethod 81 | def normalize(*args, **kwargs): # type: ignore 82 | warnings.warn( # pragma: nocover 83 | "staticmethod from_fp, from_bytes, from_path and normalize are deprecated " 84 | "and scheduled to be removed in 3.0", 85 | DeprecationWarning, 86 | ) 87 | return normalize(*args, **kwargs) # pragma: nocover 88 | 89 | 90 | class CharsetDetector(CharsetNormalizerMatches): 91 | pass 92 | 93 | 94 | class CharsetDoctor(CharsetNormalizerMatches): 95 | pass 96 | -------------------------------------------------------------------------------- /.site-packages/charset_normalizer/py.typed: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jessedobbelaere/alfred-iterm-profiles-workflow/b6b44e42b1a9c9dff6b4b4fccadcbea1210b6eea/.site-packages/charset_normalizer/py.typed -------------------------------------------------------------------------------- /.site-packages/charset_normalizer/version.py: -------------------------------------------------------------------------------- 1 | """ 2 | Expose version 3 | """ 4 | 5 | __version__ = "2.0.12" 6 | VERSION = __version__.split(".") 7 | -------------------------------------------------------------------------------- /.site-packages/idna/__init__.py: -------------------------------------------------------------------------------- 1 | from .package_data import __version__ 2 | from .core import ( 3 | IDNABidiError, 4 | IDNAError, 5 | InvalidCodepoint, 6 | InvalidCodepointContext, 7 | alabel, 8 | check_bidi, 9 | check_hyphen_ok, 10 | check_initial_combiner, 11 | check_label, 12 | check_nfc, 13 | decode, 14 | encode, 15 | ulabel, 16 | uts46_remap, 17 | valid_contextj, 18 | valid_contexto, 19 | valid_label_length, 20 | valid_string_length, 21 | ) 22 | from .intranges import intranges_contain 23 | 24 | __all__ = [ 25 | "IDNABidiError", 26 | "IDNAError", 27 | "InvalidCodepoint", 28 | "InvalidCodepointContext", 29 | "alabel", 30 | "check_bidi", 31 | "check_hyphen_ok", 32 | "check_initial_combiner", 33 | "check_label", 34 | "check_nfc", 35 | "decode", 36 | "encode", 37 | "intranges_contain", 38 | "ulabel", 39 | "uts46_remap", 40 | "valid_contextj", 41 | "valid_contexto", 42 | "valid_label_length", 43 | "valid_string_length", 44 | ] 45 | -------------------------------------------------------------------------------- /.site-packages/idna/codec.py: -------------------------------------------------------------------------------- 1 | from .core import encode, decode, alabel, ulabel, IDNAError 2 | import codecs 3 | import re 4 | from typing import Tuple, Optional 5 | 6 | _unicode_dots_re = re.compile('[\u002e\u3002\uff0e\uff61]') 7 | 8 | class Codec(codecs.Codec): 9 | 10 | def encode(self, data: str, errors: str = 'strict') -> Tuple[bytes, int]: 11 | if errors != 'strict': 12 | raise IDNAError('Unsupported error handling \"{}\"'.format(errors)) 13 | 14 | if not data: 15 | return b"", 0 16 | 17 | return encode(data), len(data) 18 | 19 | def decode(self, data: bytes, errors: str = 'strict') -> Tuple[str, int]: 20 | if errors != 'strict': 21 | raise IDNAError('Unsupported error handling \"{}\"'.format(errors)) 22 | 23 | if not data: 24 | return '', 0 25 | 26 | return decode(data), len(data) 27 | 28 | class IncrementalEncoder(codecs.BufferedIncrementalEncoder): 29 | def _buffer_encode(self, data: str, errors: str, final: bool) -> Tuple[str, int]: # type: ignore 30 | if errors != 'strict': 31 | raise IDNAError('Unsupported error handling \"{}\"'.format(errors)) 32 | 33 | if not data: 34 | return "", 0 35 | 36 | labels = _unicode_dots_re.split(data) 37 | trailing_dot = '' 38 | if labels: 39 | if not labels[-1]: 40 | trailing_dot = '.' 41 | del labels[-1] 42 | elif not final: 43 | # Keep potentially unfinished label until the next call 44 | del labels[-1] 45 | if labels: 46 | trailing_dot = '.' 47 | 48 | result = [] 49 | size = 0 50 | for label in labels: 51 | result.append(alabel(label)) 52 | if size: 53 | size += 1 54 | size += len(label) 55 | 56 | # Join with U+002E 57 | result_str = '.'.join(result) + trailing_dot # type: ignore 58 | size += len(trailing_dot) 59 | return result_str, size 60 | 61 | class IncrementalDecoder(codecs.BufferedIncrementalDecoder): 62 | def _buffer_decode(self, data: str, errors: str, final: bool) -> Tuple[str, int]: # type: ignore 63 | if errors != 'strict': 64 | raise IDNAError('Unsupported error handling \"{}\"'.format(errors)) 65 | 66 | if not data: 67 | return ('', 0) 68 | 69 | labels = _unicode_dots_re.split(data) 70 | trailing_dot = '' 71 | if labels: 72 | if not labels[-1]: 73 | trailing_dot = '.' 74 | del labels[-1] 75 | elif not final: 76 | # Keep potentially unfinished label until the next call 77 | del labels[-1] 78 | if labels: 79 | trailing_dot = '.' 80 | 81 | result = [] 82 | size = 0 83 | for label in labels: 84 | result.append(ulabel(label)) 85 | if size: 86 | size += 1 87 | size += len(label) 88 | 89 | result_str = '.'.join(result) + trailing_dot 90 | size += len(trailing_dot) 91 | return (result_str, size) 92 | 93 | 94 | class StreamWriter(Codec, codecs.StreamWriter): 95 | pass 96 | 97 | 98 | class StreamReader(Codec, codecs.StreamReader): 99 | pass 100 | 101 | 102 | def getregentry() -> codecs.CodecInfo: 103 | # Compatibility as a search_function for codecs.register() 104 | return codecs.CodecInfo( 105 | name='idna', 106 | encode=Codec().encode, # type: ignore 107 | decode=Codec().decode, # type: ignore 108 | incrementalencoder=IncrementalEncoder, 109 | incrementaldecoder=IncrementalDecoder, 110 | streamwriter=StreamWriter, 111 | streamreader=StreamReader, 112 | ) 113 | -------------------------------------------------------------------------------- /.site-packages/idna/compat.py: -------------------------------------------------------------------------------- 1 | from .core import * 2 | from .codec import * 3 | from typing import Any, Union 4 | 5 | def ToASCII(label: str) -> bytes: 6 | return encode(label) 7 | 8 | def ToUnicode(label: Union[bytes, bytearray]) -> str: 9 | return decode(label) 10 | 11 | def nameprep(s: Any) -> None: 12 | raise NotImplementedError('IDNA 2008 does not utilise nameprep protocol') 13 | 14 | -------------------------------------------------------------------------------- /.site-packages/idna/intranges.py: -------------------------------------------------------------------------------- 1 | """ 2 | Given a list of integers, made up of (hopefully) a small number of long runs 3 | of consecutive integers, compute a representation of the form 4 | ((start1, end1), (start2, end2) ...). Then answer the question "was x present 5 | in the original list?" in time O(log(# runs)). 6 | """ 7 | 8 | import bisect 9 | from typing import List, Tuple 10 | 11 | def intranges_from_list(list_: List[int]) -> Tuple[int, ...]: 12 | """Represent a list of integers as a sequence of ranges: 13 | ((start_0, end_0), (start_1, end_1), ...), such that the original 14 | integers are exactly those x such that start_i <= x < end_i for some i. 15 | 16 | Ranges are encoded as single integers (start << 32 | end), not as tuples. 17 | """ 18 | 19 | sorted_list = sorted(list_) 20 | ranges = [] 21 | last_write = -1 22 | for i in range(len(sorted_list)): 23 | if i+1 < len(sorted_list): 24 | if sorted_list[i] == sorted_list[i+1]-1: 25 | continue 26 | current_range = sorted_list[last_write+1:i+1] 27 | ranges.append(_encode_range(current_range[0], current_range[-1] + 1)) 28 | last_write = i 29 | 30 | return tuple(ranges) 31 | 32 | def _encode_range(start: int, end: int) -> int: 33 | return (start << 32) | end 34 | 35 | def _decode_range(r: int) -> Tuple[int, int]: 36 | return (r >> 32), (r & ((1 << 32) - 1)) 37 | 38 | 39 | def intranges_contain(int_: int, ranges: Tuple[int, ...]) -> bool: 40 | """Determine if `int_` falls into one of the ranges in `ranges`.""" 41 | tuple_ = _encode_range(int_, 0) 42 | pos = bisect.bisect_left(ranges, tuple_) 43 | # we could be immediately ahead of a tuple (start, end) 44 | # with start < int_ <= end 45 | if pos > 0: 46 | left, right = _decode_range(ranges[pos-1]) 47 | if left <= int_ < right: 48 | return True 49 | # or we could be immediately behind a tuple (int_, end) 50 | if pos < len(ranges): 51 | left, _ = _decode_range(ranges[pos]) 52 | if left == int_: 53 | return True 54 | return False 55 | -------------------------------------------------------------------------------- /.site-packages/idna/package_data.py: -------------------------------------------------------------------------------- 1 | __version__ = '3.3' 2 | 3 | -------------------------------------------------------------------------------- /.site-packages/idna/py.typed: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jessedobbelaere/alfred-iterm-profiles-workflow/b6b44e42b1a9c9dff6b4b4fccadcbea1210b6eea/.site-packages/idna/py.typed -------------------------------------------------------------------------------- /.site-packages/pyperclip/__main__.py: -------------------------------------------------------------------------------- 1 | import pyperclip 2 | import sys 3 | 4 | if len(sys.argv) > 1 and sys.argv[1] in ('-c', '--copy'): 5 | if len(sys.argv) > 2: 6 | pyperclip.copy(sys.argv[2]) 7 | else: 8 | pyperclip.copy(sys.stdin.read()) 9 | elif len(sys.argv) > 1 and sys.argv[1] in ('-p', '--paste'): 10 | sys.stdout.write(pyperclip.paste()) 11 | else: 12 | print('Usage: python -m pyperclip [-c | --copy] [text_to_copy] | [-p | --paste]') 13 | print() 14 | print('If a text_to_copy argument is provided, it is copied to the') 15 | print('clipboard. Otherwise, the stdin stream is copied to the') 16 | print('clipboard. (If reading this in from the keyboard, press') 17 | print('CTRL-Z on Windows or CTRL-D on Linux/macOS to stop.') 18 | print('When pasting, the clipboard will be written to stdout.') -------------------------------------------------------------------------------- /.site-packages/requests/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # __ 4 | # /__) _ _ _ _ _/ _ 5 | # / ( (- (/ (/ (- _) / _) 6 | # / 7 | 8 | """ 9 | Requests HTTP Library 10 | ~~~~~~~~~~~~~~~~~~~~~ 11 | 12 | Requests is an HTTP library, written in Python, for human beings. 13 | Basic GET usage: 14 | 15 | >>> import requests 16 | >>> r = requests.get('https://www.python.org') 17 | >>> r.status_code 18 | 200 19 | >>> b'Python is a programming language' in r.content 20 | True 21 | 22 | ... or POST: 23 | 24 | >>> payload = dict(key1='value1', key2='value2') 25 | >>> r = requests.post('https://httpbin.org/post', data=payload) 26 | >>> print(r.text) 27 | { 28 | ... 29 | "form": { 30 | "key1": "value1", 31 | "key2": "value2" 32 | }, 33 | ... 34 | } 35 | 36 | The other HTTP methods are supported - see `requests.api`. Full documentation 37 | is at . 38 | 39 | :copyright: (c) 2017 by Kenneth Reitz. 40 | :license: Apache 2.0, see LICENSE for more details. 41 | """ 42 | 43 | import urllib3 44 | import warnings 45 | from .exceptions import RequestsDependencyWarning 46 | 47 | try: 48 | from charset_normalizer import __version__ as charset_normalizer_version 49 | except ImportError: 50 | charset_normalizer_version = None 51 | 52 | try: 53 | from chardet import __version__ as chardet_version 54 | except ImportError: 55 | chardet_version = None 56 | 57 | def check_compatibility(urllib3_version, chardet_version, charset_normalizer_version): 58 | urllib3_version = urllib3_version.split('.') 59 | assert urllib3_version != ['dev'] # Verify urllib3 isn't installed from git. 60 | 61 | # Sometimes, urllib3 only reports its version as 16.1. 62 | if len(urllib3_version) == 2: 63 | urllib3_version.append('0') 64 | 65 | # Check urllib3 for compatibility. 66 | major, minor, patch = urllib3_version # noqa: F811 67 | major, minor, patch = int(major), int(minor), int(patch) 68 | # urllib3 >= 1.21.1, <= 1.26 69 | assert major == 1 70 | assert minor >= 21 71 | assert minor <= 26 72 | 73 | # Check charset_normalizer for compatibility. 74 | if chardet_version: 75 | major, minor, patch = chardet_version.split('.')[:3] 76 | major, minor, patch = int(major), int(minor), int(patch) 77 | # chardet_version >= 3.0.2, < 5.0.0 78 | assert (3, 0, 2) <= (major, minor, patch) < (5, 0, 0) 79 | elif charset_normalizer_version: 80 | major, minor, patch = charset_normalizer_version.split('.')[:3] 81 | major, minor, patch = int(major), int(minor), int(patch) 82 | # charset_normalizer >= 2.0.0 < 3.0.0 83 | assert (2, 0, 0) <= (major, minor, patch) < (3, 0, 0) 84 | else: 85 | raise Exception("You need either charset_normalizer or chardet installed") 86 | 87 | def _check_cryptography(cryptography_version): 88 | # cryptography < 1.3.4 89 | try: 90 | cryptography_version = list(map(int, cryptography_version.split('.'))) 91 | except ValueError: 92 | return 93 | 94 | if cryptography_version < [1, 3, 4]: 95 | warning = 'Old version of cryptography ({}) may cause slowdown.'.format(cryptography_version) 96 | warnings.warn(warning, RequestsDependencyWarning) 97 | 98 | # Check imported dependencies for compatibility. 99 | try: 100 | check_compatibility(urllib3.__version__, chardet_version, charset_normalizer_version) 101 | except (AssertionError, ValueError): 102 | warnings.warn("urllib3 ({}) or chardet ({})/charset_normalizer ({}) doesn't match a supported " 103 | "version!".format(urllib3.__version__, chardet_version, charset_normalizer_version), 104 | RequestsDependencyWarning) 105 | 106 | # Attempt to enable urllib3's fallback for SNI support 107 | # if the standard library doesn't support SNI or the 108 | # 'ssl' library isn't available. 109 | try: 110 | try: 111 | import ssl 112 | except ImportError: 113 | ssl = None 114 | 115 | if not getattr(ssl, "HAS_SNI", False): 116 | from urllib3.contrib import pyopenssl 117 | pyopenssl.inject_into_urllib3() 118 | 119 | # Check cryptography version 120 | from cryptography import __version__ as cryptography_version 121 | _check_cryptography(cryptography_version) 122 | except ImportError: 123 | pass 124 | 125 | # urllib3's DependencyWarnings should be silenced. 126 | from urllib3.exceptions import DependencyWarning 127 | warnings.simplefilter('ignore', DependencyWarning) 128 | 129 | from .__version__ import __title__, __description__, __url__, __version__ 130 | from .__version__ import __build__, __author__, __author_email__, __license__ 131 | from .__version__ import __copyright__, __cake__ 132 | 133 | from . import utils 134 | from . import packages 135 | from .models import Request, Response, PreparedRequest 136 | from .api import request, get, head, post, patch, put, delete, options 137 | from .sessions import session, Session 138 | from .status_codes import codes 139 | from .exceptions import ( 140 | RequestException, Timeout, URLRequired, 141 | TooManyRedirects, HTTPError, ConnectionError, 142 | FileModeWarning, ConnectTimeout, ReadTimeout, JSONDecodeError 143 | ) 144 | 145 | # Set default logging handler to avoid "No handler found" warnings. 146 | import logging 147 | from logging import NullHandler 148 | 149 | logging.getLogger(__name__).addHandler(NullHandler()) 150 | 151 | # FileModeWarnings go off per the default. 152 | warnings.simplefilter('default', FileModeWarning, append=True) 153 | -------------------------------------------------------------------------------- /.site-packages/requests/__version__.py: -------------------------------------------------------------------------------- 1 | # .-. .-. .-. . . .-. .-. .-. .-. 2 | # |( |- |.| | | |- `-. | `-. 3 | # ' ' `-' `-`.`-' `-' `-' ' `-' 4 | 5 | __title__ = 'requests' 6 | __description__ = 'Python HTTP for Humans.' 7 | __url__ = 'https://requests.readthedocs.io' 8 | __version__ = '2.27.1' 9 | __build__ = 0x022701 10 | __author__ = 'Kenneth Reitz' 11 | __author_email__ = 'me@kennethreitz.org' 12 | __license__ = 'Apache 2.0' 13 | __copyright__ = 'Copyright 2022 Kenneth Reitz' 14 | __cake__ = u'\u2728 \U0001f370 \u2728' 15 | -------------------------------------------------------------------------------- /.site-packages/requests/_internal_utils.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | """ 4 | requests._internal_utils 5 | ~~~~~~~~~~~~~~ 6 | 7 | Provides utility functions that are consumed internally by Requests 8 | which depend on extremely few external helpers (such as compat) 9 | """ 10 | 11 | from .compat import is_py2, builtin_str, str 12 | 13 | 14 | def to_native_string(string, encoding='ascii'): 15 | """Given a string object, regardless of type, returns a representation of 16 | that string in the native string type, encoding and decoding where 17 | necessary. This assumes ASCII unless told otherwise. 18 | """ 19 | if isinstance(string, builtin_str): 20 | out = string 21 | else: 22 | if is_py2: 23 | out = string.encode(encoding) 24 | else: 25 | out = string.decode(encoding) 26 | 27 | return out 28 | 29 | 30 | def unicode_is_ascii(u_string): 31 | """Determine if unicode string only contains ASCII characters. 32 | 33 | :param str u_string: unicode string to check. Must be unicode 34 | and not Python 2 `str`. 35 | :rtype: bool 36 | """ 37 | assert isinstance(u_string, str) 38 | try: 39 | u_string.encode('ascii') 40 | return True 41 | except UnicodeEncodeError: 42 | return False 43 | -------------------------------------------------------------------------------- /.site-packages/requests/certs.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | """ 5 | requests.certs 6 | ~~~~~~~~~~~~~~ 7 | 8 | This module returns the preferred default CA certificate bundle. There is 9 | only one — the one from the certifi package. 10 | 11 | If you are packaging Requests, e.g., for a Linux distribution or a managed 12 | environment, you can change the definition of where() to return a separately 13 | packaged CA bundle. 14 | """ 15 | from certifi import where 16 | 17 | if __name__ == '__main__': 18 | print(where()) 19 | -------------------------------------------------------------------------------- /.site-packages/requests/compat.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | """ 4 | requests.compat 5 | ~~~~~~~~~~~~~~~ 6 | 7 | This module handles import compatibility issues between Python 2 and 8 | Python 3. 9 | """ 10 | 11 | try: 12 | import chardet 13 | except ImportError: 14 | import charset_normalizer as chardet 15 | 16 | import sys 17 | 18 | # ------- 19 | # Pythons 20 | # ------- 21 | 22 | # Syntax sugar. 23 | _ver = sys.version_info 24 | 25 | #: Python 2.x? 26 | is_py2 = (_ver[0] == 2) 27 | 28 | #: Python 3.x? 29 | is_py3 = (_ver[0] == 3) 30 | 31 | has_simplejson = False 32 | try: 33 | import simplejson as json 34 | has_simplejson = True 35 | except ImportError: 36 | import json 37 | 38 | # --------- 39 | # Specifics 40 | # --------- 41 | 42 | if is_py2: 43 | from urllib import ( 44 | quote, unquote, quote_plus, unquote_plus, urlencode, getproxies, 45 | proxy_bypass, proxy_bypass_environment, getproxies_environment) 46 | from urlparse import urlparse, urlunparse, urljoin, urlsplit, urldefrag 47 | from urllib2 import parse_http_list 48 | import cookielib 49 | from Cookie import Morsel 50 | from StringIO import StringIO 51 | # Keep OrderedDict for backwards compatibility. 52 | from collections import Callable, Mapping, MutableMapping, OrderedDict 53 | 54 | builtin_str = str 55 | bytes = str 56 | str = unicode 57 | basestring = basestring 58 | numeric_types = (int, long, float) 59 | integer_types = (int, long) 60 | JSONDecodeError = ValueError 61 | 62 | elif is_py3: 63 | from urllib.parse import urlparse, urlunparse, urljoin, urlsplit, urlencode, quote, unquote, quote_plus, unquote_plus, urldefrag 64 | from urllib.request import parse_http_list, getproxies, proxy_bypass, proxy_bypass_environment, getproxies_environment 65 | from http import cookiejar as cookielib 66 | from http.cookies import Morsel 67 | from io import StringIO 68 | # Keep OrderedDict for backwards compatibility. 69 | from collections import OrderedDict 70 | from collections.abc import Callable, Mapping, MutableMapping 71 | if has_simplejson: 72 | from simplejson import JSONDecodeError 73 | else: 74 | from json import JSONDecodeError 75 | 76 | builtin_str = str 77 | str = str 78 | bytes = bytes 79 | basestring = (str, bytes) 80 | numeric_types = (int, float) 81 | integer_types = (int,) 82 | -------------------------------------------------------------------------------- /.site-packages/requests/exceptions.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | """ 4 | requests.exceptions 5 | ~~~~~~~~~~~~~~~~~~~ 6 | 7 | This module contains the set of Requests' exceptions. 8 | """ 9 | from urllib3.exceptions import HTTPError as BaseHTTPError 10 | 11 | from .compat import JSONDecodeError as CompatJSONDecodeError 12 | 13 | 14 | class RequestException(IOError): 15 | """There was an ambiguous exception that occurred while handling your 16 | request. 17 | """ 18 | 19 | def __init__(self, *args, **kwargs): 20 | """Initialize RequestException with `request` and `response` objects.""" 21 | response = kwargs.pop('response', None) 22 | self.response = response 23 | self.request = kwargs.pop('request', None) 24 | if (response is not None and not self.request and 25 | hasattr(response, 'request')): 26 | self.request = self.response.request 27 | super(RequestException, self).__init__(*args, **kwargs) 28 | 29 | 30 | class InvalidJSONError(RequestException): 31 | """A JSON error occurred.""" 32 | 33 | 34 | class JSONDecodeError(InvalidJSONError, CompatJSONDecodeError): 35 | """Couldn't decode the text into json""" 36 | 37 | 38 | class HTTPError(RequestException): 39 | """An HTTP error occurred.""" 40 | 41 | 42 | class ConnectionError(RequestException): 43 | """A Connection error occurred.""" 44 | 45 | 46 | class ProxyError(ConnectionError): 47 | """A proxy error occurred.""" 48 | 49 | 50 | class SSLError(ConnectionError): 51 | """An SSL error occurred.""" 52 | 53 | 54 | class Timeout(RequestException): 55 | """The request timed out. 56 | 57 | Catching this error will catch both 58 | :exc:`~requests.exceptions.ConnectTimeout` and 59 | :exc:`~requests.exceptions.ReadTimeout` errors. 60 | """ 61 | 62 | 63 | class ConnectTimeout(ConnectionError, Timeout): 64 | """The request timed out while trying to connect to the remote server. 65 | 66 | Requests that produced this error are safe to retry. 67 | """ 68 | 69 | 70 | class ReadTimeout(Timeout): 71 | """The server did not send any data in the allotted amount of time.""" 72 | 73 | 74 | class URLRequired(RequestException): 75 | """A valid URL is required to make a request.""" 76 | 77 | 78 | class TooManyRedirects(RequestException): 79 | """Too many redirects.""" 80 | 81 | 82 | class MissingSchema(RequestException, ValueError): 83 | """The URL scheme (e.g. http or https) is missing.""" 84 | 85 | 86 | class InvalidSchema(RequestException, ValueError): 87 | """The URL scheme provided is either invalid or unsupported.""" 88 | 89 | 90 | class InvalidURL(RequestException, ValueError): 91 | """The URL provided was somehow invalid.""" 92 | 93 | 94 | class InvalidHeader(RequestException, ValueError): 95 | """The header value provided was somehow invalid.""" 96 | 97 | 98 | class InvalidProxyURL(InvalidURL): 99 | """The proxy URL provided is invalid.""" 100 | 101 | 102 | class ChunkedEncodingError(RequestException): 103 | """The server declared chunked encoding but sent an invalid chunk.""" 104 | 105 | 106 | class ContentDecodingError(RequestException, BaseHTTPError): 107 | """Failed to decode response content.""" 108 | 109 | 110 | class StreamConsumedError(RequestException, TypeError): 111 | """The content for this response was already consumed.""" 112 | 113 | 114 | class RetryError(RequestException): 115 | """Custom retries logic failed""" 116 | 117 | 118 | class UnrewindableBodyError(RequestException): 119 | """Requests encountered an error when trying to rewind a body.""" 120 | 121 | # Warnings 122 | 123 | 124 | class RequestsWarning(Warning): 125 | """Base warning for Requests.""" 126 | 127 | 128 | class FileModeWarning(RequestsWarning, DeprecationWarning): 129 | """A file was opened in text mode, but Requests determined its binary length.""" 130 | 131 | 132 | class RequestsDependencyWarning(RequestsWarning): 133 | """An imported dependency doesn't match the expected version range.""" 134 | -------------------------------------------------------------------------------- /.site-packages/requests/help.py: -------------------------------------------------------------------------------- 1 | """Module containing bug report helper(s).""" 2 | from __future__ import print_function 3 | 4 | import json 5 | import platform 6 | import sys 7 | import ssl 8 | 9 | import idna 10 | import urllib3 11 | 12 | from . import __version__ as requests_version 13 | 14 | try: 15 | import charset_normalizer 16 | except ImportError: 17 | charset_normalizer = None 18 | 19 | try: 20 | import chardet 21 | except ImportError: 22 | chardet = None 23 | 24 | try: 25 | from urllib3.contrib import pyopenssl 26 | except ImportError: 27 | pyopenssl = None 28 | OpenSSL = None 29 | cryptography = None 30 | else: 31 | import OpenSSL 32 | import cryptography 33 | 34 | 35 | def _implementation(): 36 | """Return a dict with the Python implementation and version. 37 | 38 | Provide both the name and the version of the Python implementation 39 | currently running. For example, on CPython 2.7.5 it will return 40 | {'name': 'CPython', 'version': '2.7.5'}. 41 | 42 | This function works best on CPython and PyPy: in particular, it probably 43 | doesn't work for Jython or IronPython. Future investigation should be done 44 | to work out the correct shape of the code for those platforms. 45 | """ 46 | implementation = platform.python_implementation() 47 | 48 | if implementation == 'CPython': 49 | implementation_version = platform.python_version() 50 | elif implementation == 'PyPy': 51 | implementation_version = '%s.%s.%s' % (sys.pypy_version_info.major, 52 | sys.pypy_version_info.minor, 53 | sys.pypy_version_info.micro) 54 | if sys.pypy_version_info.releaselevel != 'final': 55 | implementation_version = ''.join([ 56 | implementation_version, sys.pypy_version_info.releaselevel 57 | ]) 58 | elif implementation == 'Jython': 59 | implementation_version = platform.python_version() # Complete Guess 60 | elif implementation == 'IronPython': 61 | implementation_version = platform.python_version() # Complete Guess 62 | else: 63 | implementation_version = 'Unknown' 64 | 65 | return {'name': implementation, 'version': implementation_version} 66 | 67 | 68 | def info(): 69 | """Generate information for a bug report.""" 70 | try: 71 | platform_info = { 72 | 'system': platform.system(), 73 | 'release': platform.release(), 74 | } 75 | except IOError: 76 | platform_info = { 77 | 'system': 'Unknown', 78 | 'release': 'Unknown', 79 | } 80 | 81 | implementation_info = _implementation() 82 | urllib3_info = {'version': urllib3.__version__} 83 | charset_normalizer_info = {'version': None} 84 | chardet_info = {'version': None} 85 | if charset_normalizer: 86 | charset_normalizer_info = {'version': charset_normalizer.__version__} 87 | if chardet: 88 | chardet_info = {'version': chardet.__version__} 89 | 90 | pyopenssl_info = { 91 | 'version': None, 92 | 'openssl_version': '', 93 | } 94 | if OpenSSL: 95 | pyopenssl_info = { 96 | 'version': OpenSSL.__version__, 97 | 'openssl_version': '%x' % OpenSSL.SSL.OPENSSL_VERSION_NUMBER, 98 | } 99 | cryptography_info = { 100 | 'version': getattr(cryptography, '__version__', ''), 101 | } 102 | idna_info = { 103 | 'version': getattr(idna, '__version__', ''), 104 | } 105 | 106 | system_ssl = ssl.OPENSSL_VERSION_NUMBER 107 | system_ssl_info = { 108 | 'version': '%x' % system_ssl if system_ssl is not None else '' 109 | } 110 | 111 | return { 112 | 'platform': platform_info, 113 | 'implementation': implementation_info, 114 | 'system_ssl': system_ssl_info, 115 | 'using_pyopenssl': pyopenssl is not None, 116 | 'using_charset_normalizer': chardet is None, 117 | 'pyOpenSSL': pyopenssl_info, 118 | 'urllib3': urllib3_info, 119 | 'chardet': chardet_info, 120 | 'charset_normalizer': charset_normalizer_info, 121 | 'cryptography': cryptography_info, 122 | 'idna': idna_info, 123 | 'requests': { 124 | 'version': requests_version, 125 | }, 126 | } 127 | 128 | 129 | def main(): 130 | """Pretty-print the bug information as JSON.""" 131 | print(json.dumps(info(), sort_keys=True, indent=2)) 132 | 133 | 134 | if __name__ == '__main__': 135 | main() 136 | -------------------------------------------------------------------------------- /.site-packages/requests/hooks.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | """ 4 | requests.hooks 5 | ~~~~~~~~~~~~~~ 6 | 7 | This module provides the capabilities for the Requests hooks system. 8 | 9 | Available hooks: 10 | 11 | ``response``: 12 | The response generated from a Request. 13 | """ 14 | HOOKS = ['response'] 15 | 16 | 17 | def default_hooks(): 18 | return {event: [] for event in HOOKS} 19 | 20 | # TODO: response is the only one 21 | 22 | 23 | def dispatch_hook(key, hooks, hook_data, **kwargs): 24 | """Dispatches a hook dictionary on a given piece of data.""" 25 | hooks = hooks or {} 26 | hooks = hooks.get(key) 27 | if hooks: 28 | if hasattr(hooks, '__call__'): 29 | hooks = [hooks] 30 | for hook in hooks: 31 | _hook_data = hook(hook_data, **kwargs) 32 | if _hook_data is not None: 33 | hook_data = _hook_data 34 | return hook_data 35 | -------------------------------------------------------------------------------- /.site-packages/requests/packages.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | try: 4 | import chardet 5 | except ImportError: 6 | import charset_normalizer as chardet 7 | import warnings 8 | 9 | warnings.filterwarnings('ignore', 'Trying to detect', module='charset_normalizer') 10 | 11 | # This code exists for backwards compatibility reasons. 12 | # I don't like it either. Just look the other way. :) 13 | 14 | for package in ('urllib3', 'idna'): 15 | locals()[package] = __import__(package) 16 | # This traversal is apparently necessary such that the identities are 17 | # preserved (requests.packages.urllib3.* is urllib3.*) 18 | for mod in list(sys.modules): 19 | if mod == package or mod.startswith(package + '.'): 20 | sys.modules['requests.packages.' + mod] = sys.modules[mod] 21 | 22 | target = chardet.__name__ 23 | for mod in list(sys.modules): 24 | if mod == target or mod.startswith(target + '.'): 25 | sys.modules['requests.packages.' + target.replace(target, 'chardet')] = sys.modules[mod] 26 | # Kinda cool, though, right? 27 | -------------------------------------------------------------------------------- /.site-packages/requests/status_codes.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | r""" 4 | The ``codes`` object defines a mapping from common names for HTTP statuses 5 | to their numerical codes, accessible either as attributes or as dictionary 6 | items. 7 | 8 | Example:: 9 | 10 | >>> import requests 11 | >>> requests.codes['temporary_redirect'] 12 | 307 13 | >>> requests.codes.teapot 14 | 418 15 | >>> requests.codes['\o/'] 16 | 200 17 | 18 | Some codes have multiple names, and both upper- and lower-case versions of 19 | the names are allowed. For example, ``codes.ok``, ``codes.OK``, and 20 | ``codes.okay`` all correspond to the HTTP status code 200. 21 | """ 22 | 23 | from .structures import LookupDict 24 | 25 | _codes = { 26 | 27 | # Informational. 28 | 100: ('continue',), 29 | 101: ('switching_protocols',), 30 | 102: ('processing',), 31 | 103: ('checkpoint',), 32 | 122: ('uri_too_long', 'request_uri_too_long'), 33 | 200: ('ok', 'okay', 'all_ok', 'all_okay', 'all_good', '\\o/', '✓'), 34 | 201: ('created',), 35 | 202: ('accepted',), 36 | 203: ('non_authoritative_info', 'non_authoritative_information'), 37 | 204: ('no_content',), 38 | 205: ('reset_content', 'reset'), 39 | 206: ('partial_content', 'partial'), 40 | 207: ('multi_status', 'multiple_status', 'multi_stati', 'multiple_stati'), 41 | 208: ('already_reported',), 42 | 226: ('im_used',), 43 | 44 | # Redirection. 45 | 300: ('multiple_choices',), 46 | 301: ('moved_permanently', 'moved', '\\o-'), 47 | 302: ('found',), 48 | 303: ('see_other', 'other'), 49 | 304: ('not_modified',), 50 | 305: ('use_proxy',), 51 | 306: ('switch_proxy',), 52 | 307: ('temporary_redirect', 'temporary_moved', 'temporary'), 53 | 308: ('permanent_redirect', 54 | 'resume_incomplete', 'resume',), # These 2 to be removed in 3.0 55 | 56 | # Client Error. 57 | 400: ('bad_request', 'bad'), 58 | 401: ('unauthorized',), 59 | 402: ('payment_required', 'payment'), 60 | 403: ('forbidden',), 61 | 404: ('not_found', '-o-'), 62 | 405: ('method_not_allowed', 'not_allowed'), 63 | 406: ('not_acceptable',), 64 | 407: ('proxy_authentication_required', 'proxy_auth', 'proxy_authentication'), 65 | 408: ('request_timeout', 'timeout'), 66 | 409: ('conflict',), 67 | 410: ('gone',), 68 | 411: ('length_required',), 69 | 412: ('precondition_failed', 'precondition'), 70 | 413: ('request_entity_too_large',), 71 | 414: ('request_uri_too_large',), 72 | 415: ('unsupported_media_type', 'unsupported_media', 'media_type'), 73 | 416: ('requested_range_not_satisfiable', 'requested_range', 'range_not_satisfiable'), 74 | 417: ('expectation_failed',), 75 | 418: ('im_a_teapot', 'teapot', 'i_am_a_teapot'), 76 | 421: ('misdirected_request',), 77 | 422: ('unprocessable_entity', 'unprocessable'), 78 | 423: ('locked',), 79 | 424: ('failed_dependency', 'dependency'), 80 | 425: ('unordered_collection', 'unordered'), 81 | 426: ('upgrade_required', 'upgrade'), 82 | 428: ('precondition_required', 'precondition'), 83 | 429: ('too_many_requests', 'too_many'), 84 | 431: ('header_fields_too_large', 'fields_too_large'), 85 | 444: ('no_response', 'none'), 86 | 449: ('retry_with', 'retry'), 87 | 450: ('blocked_by_windows_parental_controls', 'parental_controls'), 88 | 451: ('unavailable_for_legal_reasons', 'legal_reasons'), 89 | 499: ('client_closed_request',), 90 | 91 | # Server Error. 92 | 500: ('internal_server_error', 'server_error', '/o\\', '✗'), 93 | 501: ('not_implemented',), 94 | 502: ('bad_gateway',), 95 | 503: ('service_unavailable', 'unavailable'), 96 | 504: ('gateway_timeout',), 97 | 505: ('http_version_not_supported', 'http_version'), 98 | 506: ('variant_also_negotiates',), 99 | 507: ('insufficient_storage',), 100 | 509: ('bandwidth_limit_exceeded', 'bandwidth'), 101 | 510: ('not_extended',), 102 | 511: ('network_authentication_required', 'network_auth', 'network_authentication'), 103 | } 104 | 105 | codes = LookupDict(name='status_codes') 106 | 107 | def _init(): 108 | for code, titles in _codes.items(): 109 | for title in titles: 110 | setattr(codes, title, code) 111 | if not title.startswith(('\\', '/')): 112 | setattr(codes, title.upper(), code) 113 | 114 | def doc(code): 115 | names = ', '.join('``%s``' % n for n in _codes[code]) 116 | return '* %d: %s' % (code, names) 117 | 118 | global __doc__ 119 | __doc__ = (__doc__ + '\n' + 120 | '\n'.join(doc(code) for code in sorted(_codes)) 121 | if __doc__ is not None else None) 122 | 123 | _init() 124 | -------------------------------------------------------------------------------- /.site-packages/requests/structures.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | """ 4 | requests.structures 5 | ~~~~~~~~~~~~~~~~~~~ 6 | 7 | Data structures that power Requests. 8 | """ 9 | 10 | from collections import OrderedDict 11 | 12 | from .compat import Mapping, MutableMapping 13 | 14 | 15 | class CaseInsensitiveDict(MutableMapping): 16 | """A case-insensitive ``dict``-like object. 17 | 18 | Implements all methods and operations of 19 | ``MutableMapping`` as well as dict's ``copy``. Also 20 | provides ``lower_items``. 21 | 22 | All keys are expected to be strings. The structure remembers the 23 | case of the last key to be set, and ``iter(instance)``, 24 | ``keys()``, ``items()``, ``iterkeys()``, and ``iteritems()`` 25 | will contain case-sensitive keys. However, querying and contains 26 | testing is case insensitive:: 27 | 28 | cid = CaseInsensitiveDict() 29 | cid['Accept'] = 'application/json' 30 | cid['aCCEPT'] == 'application/json' # True 31 | list(cid) == ['Accept'] # True 32 | 33 | For example, ``headers['content-encoding']`` will return the 34 | value of a ``'Content-Encoding'`` response header, regardless 35 | of how the header name was originally stored. 36 | 37 | If the constructor, ``.update``, or equality comparison 38 | operations are given keys that have equal ``.lower()``s, the 39 | behavior is undefined. 40 | """ 41 | 42 | def __init__(self, data=None, **kwargs): 43 | self._store = OrderedDict() 44 | if data is None: 45 | data = {} 46 | self.update(data, **kwargs) 47 | 48 | def __setitem__(self, key, value): 49 | # Use the lowercased key for lookups, but store the actual 50 | # key alongside the value. 51 | self._store[key.lower()] = (key, value) 52 | 53 | def __getitem__(self, key): 54 | return self._store[key.lower()][1] 55 | 56 | def __delitem__(self, key): 57 | del self._store[key.lower()] 58 | 59 | def __iter__(self): 60 | return (casedkey for casedkey, mappedvalue in self._store.values()) 61 | 62 | def __len__(self): 63 | return len(self._store) 64 | 65 | def lower_items(self): 66 | """Like iteritems(), but with all lowercase keys.""" 67 | return ( 68 | (lowerkey, keyval[1]) 69 | for (lowerkey, keyval) 70 | in self._store.items() 71 | ) 72 | 73 | def __eq__(self, other): 74 | if isinstance(other, Mapping): 75 | other = CaseInsensitiveDict(other) 76 | else: 77 | return NotImplemented 78 | # Compare insensitively 79 | return dict(self.lower_items()) == dict(other.lower_items()) 80 | 81 | # Copy is required 82 | def copy(self): 83 | return CaseInsensitiveDict(self._store.values()) 84 | 85 | def __repr__(self): 86 | return str(dict(self.items())) 87 | 88 | 89 | class LookupDict(dict): 90 | """Dictionary lookup object.""" 91 | 92 | def __init__(self, name=None): 93 | self.name = name 94 | super(LookupDict, self).__init__() 95 | 96 | def __repr__(self): 97 | return '' % (self.name) 98 | 99 | def __getitem__(self, key): 100 | # We allow fall-through here, so values default to None 101 | 102 | return self.__dict__.get(key, None) 103 | 104 | def get(self, key, default=None): 105 | return self.__dict__.get(key, default) 106 | -------------------------------------------------------------------------------- /.site-packages/urllib3/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Python HTTP library with thread-safe connection pooling, file post support, user friendly, and more 3 | """ 4 | from __future__ import absolute_import 5 | 6 | # Set default logging handler to avoid "No handler found" warnings. 7 | import logging 8 | import warnings 9 | from logging import NullHandler 10 | 11 | from . import exceptions 12 | from ._version import __version__ 13 | from .connectionpool import HTTPConnectionPool, HTTPSConnectionPool, connection_from_url 14 | from .filepost import encode_multipart_formdata 15 | from .poolmanager import PoolManager, ProxyManager, proxy_from_url 16 | from .response import HTTPResponse 17 | from .util.request import make_headers 18 | from .util.retry import Retry 19 | from .util.timeout import Timeout 20 | from .util.url import get_host 21 | 22 | __author__ = "Andrey Petrov (andrey.petrov@shazow.net)" 23 | __license__ = "MIT" 24 | __version__ = __version__ 25 | 26 | __all__ = ( 27 | "HTTPConnectionPool", 28 | "HTTPSConnectionPool", 29 | "PoolManager", 30 | "ProxyManager", 31 | "HTTPResponse", 32 | "Retry", 33 | "Timeout", 34 | "add_stderr_logger", 35 | "connection_from_url", 36 | "disable_warnings", 37 | "encode_multipart_formdata", 38 | "get_host", 39 | "make_headers", 40 | "proxy_from_url", 41 | ) 42 | 43 | logging.getLogger(__name__).addHandler(NullHandler()) 44 | 45 | 46 | def add_stderr_logger(level=logging.DEBUG): 47 | """ 48 | Helper for quickly adding a StreamHandler to the logger. Useful for 49 | debugging. 50 | 51 | Returns the handler after adding it. 52 | """ 53 | # This method needs to be in this __init__.py to get the __name__ correct 54 | # even if urllib3 is vendored within another package. 55 | logger = logging.getLogger(__name__) 56 | handler = logging.StreamHandler() 57 | handler.setFormatter(logging.Formatter("%(asctime)s %(levelname)s %(message)s")) 58 | logger.addHandler(handler) 59 | logger.setLevel(level) 60 | logger.debug("Added a stderr logging handler to logger: %s", __name__) 61 | return handler 62 | 63 | 64 | # ... Clean up. 65 | del NullHandler 66 | 67 | 68 | # All warning filters *must* be appended unless you're really certain that they 69 | # shouldn't be: otherwise, it's very hard for users to use most Python 70 | # mechanisms to silence them. 71 | # SecurityWarning's always go off by default. 72 | warnings.simplefilter("always", exceptions.SecurityWarning, append=True) 73 | # SubjectAltNameWarning's should go off once per host 74 | warnings.simplefilter("default", exceptions.SubjectAltNameWarning, append=True) 75 | # InsecurePlatformWarning's don't vary between requests, so we keep it default. 76 | warnings.simplefilter("default", exceptions.InsecurePlatformWarning, append=True) 77 | # SNIMissingWarnings should go off only once. 78 | warnings.simplefilter("default", exceptions.SNIMissingWarning, append=True) 79 | 80 | 81 | def disable_warnings(category=exceptions.HTTPWarning): 82 | """ 83 | Helper for quickly disabling all urllib3 warnings. 84 | """ 85 | warnings.simplefilter("ignore", category) 86 | -------------------------------------------------------------------------------- /.site-packages/urllib3/_version.py: -------------------------------------------------------------------------------- 1 | # This file is protected via CODEOWNERS 2 | __version__ = "1.26.9" 3 | -------------------------------------------------------------------------------- /.site-packages/urllib3/contrib/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jessedobbelaere/alfred-iterm-profiles-workflow/b6b44e42b1a9c9dff6b4b4fccadcbea1210b6eea/.site-packages/urllib3/contrib/__init__.py -------------------------------------------------------------------------------- /.site-packages/urllib3/contrib/_appengine_environ.py: -------------------------------------------------------------------------------- 1 | """ 2 | This module provides means to detect the App Engine environment. 3 | """ 4 | 5 | import os 6 | 7 | 8 | def is_appengine(): 9 | return is_local_appengine() or is_prod_appengine() 10 | 11 | 12 | def is_appengine_sandbox(): 13 | """Reports if the app is running in the first generation sandbox. 14 | 15 | The second generation runtimes are technically still in a sandbox, but it 16 | is much less restrictive, so generally you shouldn't need to check for it. 17 | see https://cloud.google.com/appengine/docs/standard/runtimes 18 | """ 19 | return is_appengine() and os.environ["APPENGINE_RUNTIME"] == "python27" 20 | 21 | 22 | def is_local_appengine(): 23 | return "APPENGINE_RUNTIME" in os.environ and os.environ.get( 24 | "SERVER_SOFTWARE", "" 25 | ).startswith("Development/") 26 | 27 | 28 | def is_prod_appengine(): 29 | return "APPENGINE_RUNTIME" in os.environ and os.environ.get( 30 | "SERVER_SOFTWARE", "" 31 | ).startswith("Google App Engine/") 32 | 33 | 34 | def is_prod_appengine_mvms(): 35 | """Deprecated.""" 36 | return False 37 | -------------------------------------------------------------------------------- /.site-packages/urllib3/contrib/_securetransport/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jessedobbelaere/alfred-iterm-profiles-workflow/b6b44e42b1a9c9dff6b4b4fccadcbea1210b6eea/.site-packages/urllib3/contrib/_securetransport/__init__.py -------------------------------------------------------------------------------- /.site-packages/urllib3/contrib/ntlmpool.py: -------------------------------------------------------------------------------- 1 | """ 2 | NTLM authenticating pool, contributed by erikcederstran 3 | 4 | Issue #10, see: http://code.google.com/p/urllib3/issues/detail?id=10 5 | """ 6 | from __future__ import absolute_import 7 | 8 | import warnings 9 | from logging import getLogger 10 | 11 | from ntlm import ntlm 12 | 13 | from .. import HTTPSConnectionPool 14 | from ..packages.six.moves.http_client import HTTPSConnection 15 | 16 | warnings.warn( 17 | "The 'urllib3.contrib.ntlmpool' module is deprecated and will be removed " 18 | "in urllib3 v2.0 release, urllib3 is not able to support it properly due " 19 | "to reasons listed in issue: https://github.com/urllib3/urllib3/issues/2282. " 20 | "If you are a user of this module please comment in the mentioned issue.", 21 | DeprecationWarning, 22 | ) 23 | 24 | log = getLogger(__name__) 25 | 26 | 27 | class NTLMConnectionPool(HTTPSConnectionPool): 28 | """ 29 | Implements an NTLM authentication version of an urllib3 connection pool 30 | """ 31 | 32 | scheme = "https" 33 | 34 | def __init__(self, user, pw, authurl, *args, **kwargs): 35 | """ 36 | authurl is a random URL on the server that is protected by NTLM. 37 | user is the Windows user, probably in the DOMAIN\\username format. 38 | pw is the password for the user. 39 | """ 40 | super(NTLMConnectionPool, self).__init__(*args, **kwargs) 41 | self.authurl = authurl 42 | self.rawuser = user 43 | user_parts = user.split("\\", 1) 44 | self.domain = user_parts[0].upper() 45 | self.user = user_parts[1] 46 | self.pw = pw 47 | 48 | def _new_conn(self): 49 | # Performs the NTLM handshake that secures the connection. The socket 50 | # must be kept open while requests are performed. 51 | self.num_connections += 1 52 | log.debug( 53 | "Starting NTLM HTTPS connection no. %d: https://%s%s", 54 | self.num_connections, 55 | self.host, 56 | self.authurl, 57 | ) 58 | 59 | headers = {"Connection": "Keep-Alive"} 60 | req_header = "Authorization" 61 | resp_header = "www-authenticate" 62 | 63 | conn = HTTPSConnection(host=self.host, port=self.port) 64 | 65 | # Send negotiation message 66 | headers[req_header] = "NTLM %s" % ntlm.create_NTLM_NEGOTIATE_MESSAGE( 67 | self.rawuser 68 | ) 69 | log.debug("Request headers: %s", headers) 70 | conn.request("GET", self.authurl, None, headers) 71 | res = conn.getresponse() 72 | reshdr = dict(res.getheaders()) 73 | log.debug("Response status: %s %s", res.status, res.reason) 74 | log.debug("Response headers: %s", reshdr) 75 | log.debug("Response data: %s [...]", res.read(100)) 76 | 77 | # Remove the reference to the socket, so that it can not be closed by 78 | # the response object (we want to keep the socket open) 79 | res.fp = None 80 | 81 | # Server should respond with a challenge message 82 | auth_header_values = reshdr[resp_header].split(", ") 83 | auth_header_value = None 84 | for s in auth_header_values: 85 | if s[:5] == "NTLM ": 86 | auth_header_value = s[5:] 87 | if auth_header_value is None: 88 | raise Exception( 89 | "Unexpected %s response header: %s" % (resp_header, reshdr[resp_header]) 90 | ) 91 | 92 | # Send authentication message 93 | ServerChallenge, NegotiateFlags = ntlm.parse_NTLM_CHALLENGE_MESSAGE( 94 | auth_header_value 95 | ) 96 | auth_msg = ntlm.create_NTLM_AUTHENTICATE_MESSAGE( 97 | ServerChallenge, self.user, self.domain, self.pw, NegotiateFlags 98 | ) 99 | headers[req_header] = "NTLM %s" % auth_msg 100 | log.debug("Request headers: %s", headers) 101 | conn.request("GET", self.authurl, None, headers) 102 | res = conn.getresponse() 103 | log.debug("Response status: %s %s", res.status, res.reason) 104 | log.debug("Response headers: %s", dict(res.getheaders())) 105 | log.debug("Response data: %s [...]", res.read()[:100]) 106 | if res.status != 200: 107 | if res.status == 401: 108 | raise Exception("Server rejected request: wrong username or password") 109 | raise Exception("Wrong server response: %s %s" % (res.status, res.reason)) 110 | 111 | res.fp = None 112 | log.debug("Connection established") 113 | return conn 114 | 115 | def urlopen( 116 | self, 117 | method, 118 | url, 119 | body=None, 120 | headers=None, 121 | retries=3, 122 | redirect=True, 123 | assert_same_host=True, 124 | ): 125 | if headers is None: 126 | headers = {} 127 | headers["Connection"] = "Keep-Alive" 128 | return super(NTLMConnectionPool, self).urlopen( 129 | method, url, body, headers, retries, redirect, assert_same_host 130 | ) 131 | -------------------------------------------------------------------------------- /.site-packages/urllib3/filepost.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | 3 | import binascii 4 | import codecs 5 | import os 6 | from io import BytesIO 7 | 8 | from .fields import RequestField 9 | from .packages import six 10 | from .packages.six import b 11 | 12 | writer = codecs.lookup("utf-8")[3] 13 | 14 | 15 | def choose_boundary(): 16 | """ 17 | Our embarrassingly-simple replacement for mimetools.choose_boundary. 18 | """ 19 | boundary = binascii.hexlify(os.urandom(16)) 20 | if not six.PY2: 21 | boundary = boundary.decode("ascii") 22 | return boundary 23 | 24 | 25 | def iter_field_objects(fields): 26 | """ 27 | Iterate over fields. 28 | 29 | Supports list of (k, v) tuples and dicts, and lists of 30 | :class:`~urllib3.fields.RequestField`. 31 | 32 | """ 33 | if isinstance(fields, dict): 34 | i = six.iteritems(fields) 35 | else: 36 | i = iter(fields) 37 | 38 | for field in i: 39 | if isinstance(field, RequestField): 40 | yield field 41 | else: 42 | yield RequestField.from_tuples(*field) 43 | 44 | 45 | def iter_fields(fields): 46 | """ 47 | .. deprecated:: 1.6 48 | 49 | Iterate over fields. 50 | 51 | The addition of :class:`~urllib3.fields.RequestField` makes this function 52 | obsolete. Instead, use :func:`iter_field_objects`, which returns 53 | :class:`~urllib3.fields.RequestField` objects. 54 | 55 | Supports list of (k, v) tuples and dicts. 56 | """ 57 | if isinstance(fields, dict): 58 | return ((k, v) for k, v in six.iteritems(fields)) 59 | 60 | return ((k, v) for k, v in fields) 61 | 62 | 63 | def encode_multipart_formdata(fields, boundary=None): 64 | """ 65 | Encode a dictionary of ``fields`` using the multipart/form-data MIME format. 66 | 67 | :param fields: 68 | Dictionary of fields or list of (key, :class:`~urllib3.fields.RequestField`). 69 | 70 | :param boundary: 71 | If not specified, then a random boundary will be generated using 72 | :func:`urllib3.filepost.choose_boundary`. 73 | """ 74 | body = BytesIO() 75 | if boundary is None: 76 | boundary = choose_boundary() 77 | 78 | for field in iter_field_objects(fields): 79 | body.write(b("--%s\r\n" % (boundary))) 80 | 81 | writer(body).write(field.render_headers()) 82 | data = field.data 83 | 84 | if isinstance(data, int): 85 | data = str(data) # Backwards compatibility 86 | 87 | if isinstance(data, six.text_type): 88 | writer(body).write(data) 89 | else: 90 | body.write(data) 91 | 92 | body.write(b"\r\n") 93 | 94 | body.write(b("--%s--\r\n" % (boundary))) 95 | 96 | content_type = str("multipart/form-data; boundary=%s" % boundary) 97 | 98 | return body.getvalue(), content_type 99 | -------------------------------------------------------------------------------- /.site-packages/urllib3/packages/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jessedobbelaere/alfred-iterm-profiles-workflow/b6b44e42b1a9c9dff6b4b4fccadcbea1210b6eea/.site-packages/urllib3/packages/__init__.py -------------------------------------------------------------------------------- /.site-packages/urllib3/packages/backports/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jessedobbelaere/alfred-iterm-profiles-workflow/b6b44e42b1a9c9dff6b4b4fccadcbea1210b6eea/.site-packages/urllib3/packages/backports/__init__.py -------------------------------------------------------------------------------- /.site-packages/urllib3/packages/backports/makefile.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | backports.makefile 4 | ~~~~~~~~~~~~~~~~~~ 5 | 6 | Backports the Python 3 ``socket.makefile`` method for use with anything that 7 | wants to create a "fake" socket object. 8 | """ 9 | import io 10 | from socket import SocketIO 11 | 12 | 13 | def backport_makefile( 14 | self, mode="r", buffering=None, encoding=None, errors=None, newline=None 15 | ): 16 | """ 17 | Backport of ``socket.makefile`` from Python 3.5. 18 | """ 19 | if not set(mode) <= {"r", "w", "b"}: 20 | raise ValueError("invalid mode %r (only r, w, b allowed)" % (mode,)) 21 | writing = "w" in mode 22 | reading = "r" in mode or not writing 23 | assert reading or writing 24 | binary = "b" in mode 25 | rawmode = "" 26 | if reading: 27 | rawmode += "r" 28 | if writing: 29 | rawmode += "w" 30 | raw = SocketIO(self, rawmode) 31 | self._makefile_refs += 1 32 | if buffering is None: 33 | buffering = -1 34 | if buffering < 0: 35 | buffering = io.DEFAULT_BUFFER_SIZE 36 | if buffering == 0: 37 | if not binary: 38 | raise ValueError("unbuffered streams must be binary") 39 | return raw 40 | if reading and writing: 41 | buffer = io.BufferedRWPair(raw, raw, buffering) 42 | elif reading: 43 | buffer = io.BufferedReader(raw, buffering) 44 | else: 45 | assert writing 46 | buffer = io.BufferedWriter(raw, buffering) 47 | if binary: 48 | return buffer 49 | text = io.TextIOWrapper(buffer, encoding, errors, newline) 50 | text.mode = mode 51 | return text 52 | -------------------------------------------------------------------------------- /.site-packages/urllib3/util/__init__.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | 3 | # For backwards compatibility, provide imports that used to be here. 4 | from .connection import is_connection_dropped 5 | from .request import SKIP_HEADER, SKIPPABLE_HEADERS, make_headers 6 | from .response import is_fp_closed 7 | from .retry import Retry 8 | from .ssl_ import ( 9 | ALPN_PROTOCOLS, 10 | HAS_SNI, 11 | IS_PYOPENSSL, 12 | IS_SECURETRANSPORT, 13 | PROTOCOL_TLS, 14 | SSLContext, 15 | assert_fingerprint, 16 | resolve_cert_reqs, 17 | resolve_ssl_version, 18 | ssl_wrap_socket, 19 | ) 20 | from .timeout import Timeout, current_time 21 | from .url import Url, get_host, parse_url, split_first 22 | from .wait import wait_for_read, wait_for_write 23 | 24 | __all__ = ( 25 | "HAS_SNI", 26 | "IS_PYOPENSSL", 27 | "IS_SECURETRANSPORT", 28 | "SSLContext", 29 | "PROTOCOL_TLS", 30 | "ALPN_PROTOCOLS", 31 | "Retry", 32 | "Timeout", 33 | "Url", 34 | "assert_fingerprint", 35 | "current_time", 36 | "is_connection_dropped", 37 | "is_fp_closed", 38 | "get_host", 39 | "parse_url", 40 | "make_headers", 41 | "resolve_cert_reqs", 42 | "resolve_ssl_version", 43 | "split_first", 44 | "ssl_wrap_socket", 45 | "wait_for_read", 46 | "wait_for_write", 47 | "SKIP_HEADER", 48 | "SKIPPABLE_HEADERS", 49 | ) 50 | -------------------------------------------------------------------------------- /.site-packages/urllib3/util/connection.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | 3 | import socket 4 | 5 | from ..contrib import _appengine_environ 6 | from ..exceptions import LocationParseError 7 | from ..packages import six 8 | from .wait import NoWayToWaitForSocketError, wait_for_read 9 | 10 | 11 | def is_connection_dropped(conn): # Platform-specific 12 | """ 13 | Returns True if the connection is dropped and should be closed. 14 | 15 | :param conn: 16 | :class:`http.client.HTTPConnection` object. 17 | 18 | Note: For platforms like AppEngine, this will always return ``False`` to 19 | let the platform handle connection recycling transparently for us. 20 | """ 21 | sock = getattr(conn, "sock", False) 22 | if sock is False: # Platform-specific: AppEngine 23 | return False 24 | if sock is None: # Connection already closed (such as by httplib). 25 | return True 26 | try: 27 | # Returns True if readable, which here means it's been dropped 28 | return wait_for_read(sock, timeout=0.0) 29 | except NoWayToWaitForSocketError: # Platform-specific: AppEngine 30 | return False 31 | 32 | 33 | # This function is copied from socket.py in the Python 2.7 standard 34 | # library test suite. Added to its signature is only `socket_options`. 35 | # One additional modification is that we avoid binding to IPv6 servers 36 | # discovered in DNS if the system doesn't have IPv6 functionality. 37 | def create_connection( 38 | address, 39 | timeout=socket._GLOBAL_DEFAULT_TIMEOUT, 40 | source_address=None, 41 | socket_options=None, 42 | ): 43 | """Connect to *address* and return the socket object. 44 | 45 | Convenience function. Connect to *address* (a 2-tuple ``(host, 46 | port)``) and return the socket object. Passing the optional 47 | *timeout* parameter will set the timeout on the socket instance 48 | before attempting to connect. If no *timeout* is supplied, the 49 | global default timeout setting returned by :func:`socket.getdefaulttimeout` 50 | is used. If *source_address* is set it must be a tuple of (host, port) 51 | for the socket to bind as a source address before making the connection. 52 | An host of '' or port 0 tells the OS to use the default. 53 | """ 54 | 55 | host, port = address 56 | if host.startswith("["): 57 | host = host.strip("[]") 58 | err = None 59 | 60 | # Using the value from allowed_gai_family() in the context of getaddrinfo lets 61 | # us select whether to work with IPv4 DNS records, IPv6 records, or both. 62 | # The original create_connection function always returns all records. 63 | family = allowed_gai_family() 64 | 65 | try: 66 | host.encode("idna") 67 | except UnicodeError: 68 | return six.raise_from( 69 | LocationParseError(u"'%s', label empty or too long" % host), None 70 | ) 71 | 72 | for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): 73 | af, socktype, proto, canonname, sa = res 74 | sock = None 75 | try: 76 | sock = socket.socket(af, socktype, proto) 77 | 78 | # If provided, set socket level options before connecting. 79 | _set_socket_options(sock, socket_options) 80 | 81 | if timeout is not socket._GLOBAL_DEFAULT_TIMEOUT: 82 | sock.settimeout(timeout) 83 | if source_address: 84 | sock.bind(source_address) 85 | sock.connect(sa) 86 | return sock 87 | 88 | except socket.error as e: 89 | err = e 90 | if sock is not None: 91 | sock.close() 92 | sock = None 93 | 94 | if err is not None: 95 | raise err 96 | 97 | raise socket.error("getaddrinfo returns an empty list") 98 | 99 | 100 | def _set_socket_options(sock, options): 101 | if options is None: 102 | return 103 | 104 | for opt in options: 105 | sock.setsockopt(*opt) 106 | 107 | 108 | def allowed_gai_family(): 109 | """This function is designed to work in the context of 110 | getaddrinfo, where family=socket.AF_UNSPEC is the default and 111 | will perform a DNS search for both IPv6 and IPv4 records.""" 112 | 113 | family = socket.AF_INET 114 | if HAS_IPV6: 115 | family = socket.AF_UNSPEC 116 | return family 117 | 118 | 119 | def _has_ipv6(host): 120 | """Returns True if the system can bind an IPv6 address.""" 121 | sock = None 122 | has_ipv6 = False 123 | 124 | # App Engine doesn't support IPV6 sockets and actually has a quota on the 125 | # number of sockets that can be used, so just early out here instead of 126 | # creating a socket needlessly. 127 | # See https://github.com/urllib3/urllib3/issues/1446 128 | if _appengine_environ.is_appengine_sandbox(): 129 | return False 130 | 131 | if socket.has_ipv6: 132 | # has_ipv6 returns true if cPython was compiled with IPv6 support. 133 | # It does not tell us if the system has IPv6 support enabled. To 134 | # determine that we must bind to an IPv6 address. 135 | # https://github.com/urllib3/urllib3/pull/611 136 | # https://bugs.python.org/issue658327 137 | try: 138 | sock = socket.socket(socket.AF_INET6) 139 | sock.bind((host, 0)) 140 | has_ipv6 = True 141 | except Exception: 142 | pass 143 | 144 | if sock: 145 | sock.close() 146 | return has_ipv6 147 | 148 | 149 | HAS_IPV6 = _has_ipv6("::1") 150 | -------------------------------------------------------------------------------- /.site-packages/urllib3/util/proxy.py: -------------------------------------------------------------------------------- 1 | from .ssl_ import create_urllib3_context, resolve_cert_reqs, resolve_ssl_version 2 | 3 | 4 | def connection_requires_http_tunnel( 5 | proxy_url=None, proxy_config=None, destination_scheme=None 6 | ): 7 | """ 8 | Returns True if the connection requires an HTTP CONNECT through the proxy. 9 | 10 | :param URL proxy_url: 11 | URL of the proxy. 12 | :param ProxyConfig proxy_config: 13 | Proxy configuration from poolmanager.py 14 | :param str destination_scheme: 15 | The scheme of the destination. (i.e https, http, etc) 16 | """ 17 | # If we're not using a proxy, no way to use a tunnel. 18 | if proxy_url is None: 19 | return False 20 | 21 | # HTTP destinations never require tunneling, we always forward. 22 | if destination_scheme == "http": 23 | return False 24 | 25 | # Support for forwarding with HTTPS proxies and HTTPS destinations. 26 | if ( 27 | proxy_url.scheme == "https" 28 | and proxy_config 29 | and proxy_config.use_forwarding_for_https 30 | ): 31 | return False 32 | 33 | # Otherwise always use a tunnel. 34 | return True 35 | 36 | 37 | def create_proxy_ssl_context( 38 | ssl_version, cert_reqs, ca_certs=None, ca_cert_dir=None, ca_cert_data=None 39 | ): 40 | """ 41 | Generates a default proxy ssl context if one hasn't been provided by the 42 | user. 43 | """ 44 | ssl_context = create_urllib3_context( 45 | ssl_version=resolve_ssl_version(ssl_version), 46 | cert_reqs=resolve_cert_reqs(cert_reqs), 47 | ) 48 | 49 | if ( 50 | not ca_certs 51 | and not ca_cert_dir 52 | and not ca_cert_data 53 | and hasattr(ssl_context, "load_default_certs") 54 | ): 55 | ssl_context.load_default_certs() 56 | 57 | return ssl_context 58 | -------------------------------------------------------------------------------- /.site-packages/urllib3/util/queue.py: -------------------------------------------------------------------------------- 1 | import collections 2 | 3 | from ..packages import six 4 | from ..packages.six.moves import queue 5 | 6 | if six.PY2: 7 | # Queue is imported for side effects on MS Windows. See issue #229. 8 | import Queue as _unused_module_Queue # noqa: F401 9 | 10 | 11 | class LifoQueue(queue.Queue): 12 | def _init(self, _): 13 | self.queue = collections.deque() 14 | 15 | def _qsize(self, len=len): 16 | return len(self.queue) 17 | 18 | def _put(self, item): 19 | self.queue.append(item) 20 | 21 | def _get(self): 22 | return self.queue.pop() 23 | -------------------------------------------------------------------------------- /.site-packages/urllib3/util/request.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | 3 | from base64 import b64encode 4 | 5 | from ..exceptions import UnrewindableBodyError 6 | from ..packages.six import b, integer_types 7 | 8 | # Pass as a value within ``headers`` to skip 9 | # emitting some HTTP headers that are added automatically. 10 | # The only headers that are supported are ``Accept-Encoding``, 11 | # ``Host``, and ``User-Agent``. 12 | SKIP_HEADER = "@@@SKIP_HEADER@@@" 13 | SKIPPABLE_HEADERS = frozenset(["accept-encoding", "host", "user-agent"]) 14 | 15 | ACCEPT_ENCODING = "gzip,deflate" 16 | try: 17 | try: 18 | import brotlicffi as _unused_module_brotli # noqa: F401 19 | except ImportError: 20 | import brotli as _unused_module_brotli # noqa: F401 21 | except ImportError: 22 | pass 23 | else: 24 | ACCEPT_ENCODING += ",br" 25 | 26 | _FAILEDTELL = object() 27 | 28 | 29 | def make_headers( 30 | keep_alive=None, 31 | accept_encoding=None, 32 | user_agent=None, 33 | basic_auth=None, 34 | proxy_basic_auth=None, 35 | disable_cache=None, 36 | ): 37 | """ 38 | Shortcuts for generating request headers. 39 | 40 | :param keep_alive: 41 | If ``True``, adds 'connection: keep-alive' header. 42 | 43 | :param accept_encoding: 44 | Can be a boolean, list, or string. 45 | ``True`` translates to 'gzip,deflate'. 46 | List will get joined by comma. 47 | String will be used as provided. 48 | 49 | :param user_agent: 50 | String representing the user-agent you want, such as 51 | "python-urllib3/0.6" 52 | 53 | :param basic_auth: 54 | Colon-separated username:password string for 'authorization: basic ...' 55 | auth header. 56 | 57 | :param proxy_basic_auth: 58 | Colon-separated username:password string for 'proxy-authorization: basic ...' 59 | auth header. 60 | 61 | :param disable_cache: 62 | If ``True``, adds 'cache-control: no-cache' header. 63 | 64 | Example:: 65 | 66 | >>> make_headers(keep_alive=True, user_agent="Batman/1.0") 67 | {'connection': 'keep-alive', 'user-agent': 'Batman/1.0'} 68 | >>> make_headers(accept_encoding=True) 69 | {'accept-encoding': 'gzip,deflate'} 70 | """ 71 | headers = {} 72 | if accept_encoding: 73 | if isinstance(accept_encoding, str): 74 | pass 75 | elif isinstance(accept_encoding, list): 76 | accept_encoding = ",".join(accept_encoding) 77 | else: 78 | accept_encoding = ACCEPT_ENCODING 79 | headers["accept-encoding"] = accept_encoding 80 | 81 | if user_agent: 82 | headers["user-agent"] = user_agent 83 | 84 | if keep_alive: 85 | headers["connection"] = "keep-alive" 86 | 87 | if basic_auth: 88 | headers["authorization"] = "Basic " + b64encode(b(basic_auth)).decode("utf-8") 89 | 90 | if proxy_basic_auth: 91 | headers["proxy-authorization"] = "Basic " + b64encode( 92 | b(proxy_basic_auth) 93 | ).decode("utf-8") 94 | 95 | if disable_cache: 96 | headers["cache-control"] = "no-cache" 97 | 98 | return headers 99 | 100 | 101 | def set_file_position(body, pos): 102 | """ 103 | If a position is provided, move file to that point. 104 | Otherwise, we'll attempt to record a position for future use. 105 | """ 106 | if pos is not None: 107 | rewind_body(body, pos) 108 | elif getattr(body, "tell", None) is not None: 109 | try: 110 | pos = body.tell() 111 | except (IOError, OSError): 112 | # This differentiates from None, allowing us to catch 113 | # a failed `tell()` later when trying to rewind the body. 114 | pos = _FAILEDTELL 115 | 116 | return pos 117 | 118 | 119 | def rewind_body(body, body_pos): 120 | """ 121 | Attempt to rewind body to a certain position. 122 | Primarily used for request redirects and retries. 123 | 124 | :param body: 125 | File-like object that supports seek. 126 | 127 | :param int pos: 128 | Position to seek to in file. 129 | """ 130 | body_seek = getattr(body, "seek", None) 131 | if body_seek is not None and isinstance(body_pos, integer_types): 132 | try: 133 | body_seek(body_pos) 134 | except (IOError, OSError): 135 | raise UnrewindableBodyError( 136 | "An error occurred when rewinding request body for redirect/retry." 137 | ) 138 | elif body_pos is _FAILEDTELL: 139 | raise UnrewindableBodyError( 140 | "Unable to record file position for rewinding " 141 | "request body during a redirect/retry." 142 | ) 143 | else: 144 | raise ValueError( 145 | "body_pos must be of type integer, instead it was %s." % type(body_pos) 146 | ) 147 | -------------------------------------------------------------------------------- /.site-packages/urllib3/util/response.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | 3 | from email.errors import MultipartInvariantViolationDefect, StartBoundaryNotFoundDefect 4 | 5 | from ..exceptions import HeaderParsingError 6 | from ..packages.six.moves import http_client as httplib 7 | 8 | 9 | def is_fp_closed(obj): 10 | """ 11 | Checks whether a given file-like object is closed. 12 | 13 | :param obj: 14 | The file-like object to check. 15 | """ 16 | 17 | try: 18 | # Check `isclosed()` first, in case Python3 doesn't set `closed`. 19 | # GH Issue #928 20 | return obj.isclosed() 21 | except AttributeError: 22 | pass 23 | 24 | try: 25 | # Check via the official file-like-object way. 26 | return obj.closed 27 | except AttributeError: 28 | pass 29 | 30 | try: 31 | # Check if the object is a container for another file-like object that 32 | # gets released on exhaustion (e.g. HTTPResponse). 33 | return obj.fp is None 34 | except AttributeError: 35 | pass 36 | 37 | raise ValueError("Unable to determine whether fp is closed.") 38 | 39 | 40 | def assert_header_parsing(headers): 41 | """ 42 | Asserts whether all headers have been successfully parsed. 43 | Extracts encountered errors from the result of parsing headers. 44 | 45 | Only works on Python 3. 46 | 47 | :param http.client.HTTPMessage headers: Headers to verify. 48 | 49 | :raises urllib3.exceptions.HeaderParsingError: 50 | If parsing errors are found. 51 | """ 52 | 53 | # This will fail silently if we pass in the wrong kind of parameter. 54 | # To make debugging easier add an explicit check. 55 | if not isinstance(headers, httplib.HTTPMessage): 56 | raise TypeError("expected httplib.Message, got {0}.".format(type(headers))) 57 | 58 | defects = getattr(headers, "defects", None) 59 | get_payload = getattr(headers, "get_payload", None) 60 | 61 | unparsed_data = None 62 | if get_payload: 63 | # get_payload is actually email.message.Message.get_payload; 64 | # we're only interested in the result if it's not a multipart message 65 | if not headers.is_multipart(): 66 | payload = get_payload() 67 | 68 | if isinstance(payload, (bytes, str)): 69 | unparsed_data = payload 70 | if defects: 71 | # httplib is assuming a response body is available 72 | # when parsing headers even when httplib only sends 73 | # header data to parse_headers() This results in 74 | # defects on multipart responses in particular. 75 | # See: https://github.com/urllib3/urllib3/issues/800 76 | 77 | # So we ignore the following defects: 78 | # - StartBoundaryNotFoundDefect: 79 | # The claimed start boundary was never found. 80 | # - MultipartInvariantViolationDefect: 81 | # A message claimed to be a multipart but no subparts were found. 82 | defects = [ 83 | defect 84 | for defect in defects 85 | if not isinstance( 86 | defect, (StartBoundaryNotFoundDefect, MultipartInvariantViolationDefect) 87 | ) 88 | ] 89 | 90 | if defects or unparsed_data: 91 | raise HeaderParsingError(defects=defects, unparsed_data=unparsed_data) 92 | 93 | 94 | def is_response_to_head(response): 95 | """ 96 | Checks whether the request of a response has been a HEAD-request. 97 | Handles the quirks of AppEngine. 98 | 99 | :param http.client.HTTPResponse response: 100 | Response to check if the originating request 101 | used 'HEAD' as a method. 102 | """ 103 | # FIXME: Can we do this somehow without accessing private httplib _method? 104 | method = response._method 105 | if isinstance(method, int): # Platform-specific: Appengine 106 | return method == 3 107 | return method.upper() == "HEAD" 108 | -------------------------------------------------------------------------------- /.site-packages/workflow/Notify.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jessedobbelaere/alfred-iterm-profiles-workflow/b6b44e42b1a9c9dff6b4b4fccadcbea1210b6eea/.site-packages/workflow/Notify.tgz -------------------------------------------------------------------------------- /.site-packages/workflow/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | # 4 | # Copyright (c) 2014 Dean Jackson 5 | # 6 | # MIT Licence. See http://opensource.org/licenses/MIT 7 | # 8 | # Created on 2014-02-15 9 | # 10 | 11 | """A helper library for `Alfred `_ workflows.""" 12 | 13 | import os 14 | 15 | # Filter matching rules 16 | # Icons 17 | # Exceptions 18 | # Workflow objects 19 | from .workflow import ( 20 | ICON_ACCOUNT, 21 | ICON_BURN, 22 | ICON_CLOCK, 23 | ICON_COLOR, 24 | ICON_COLOUR, 25 | ICON_EJECT, 26 | ICON_ERROR, 27 | ICON_FAVORITE, 28 | ICON_FAVOURITE, 29 | ICON_GROUP, 30 | ICON_HELP, 31 | ICON_HOME, 32 | ICON_INFO, 33 | ICON_NETWORK, 34 | ICON_NOTE, 35 | ICON_SETTINGS, 36 | ICON_SWIRL, 37 | ICON_SWITCH, 38 | ICON_SYNC, 39 | ICON_TRASH, 40 | ICON_USER, 41 | ICON_WARNING, 42 | ICON_WEB, 43 | MATCH_ALL, 44 | MATCH_ALLCHARS, 45 | MATCH_ATOM, 46 | MATCH_CAPITALS, 47 | MATCH_INITIALS, 48 | MATCH_INITIALS_CONTAIN, 49 | MATCH_INITIALS_STARTSWITH, 50 | MATCH_STARTSWITH, 51 | MATCH_SUBSTRING, 52 | KeychainError, 53 | PasswordNotFound, 54 | Workflow, 55 | manager, 56 | ) 57 | from .workflow3 import Variables, Workflow3 58 | 59 | __title__ = "Alfred-Workflow" 60 | __version__ = open(os.path.join(os.path.dirname(__file__), "version")).read() 61 | __author__ = "Dean Jackson" 62 | __licence__ = "MIT" 63 | __copyright__ = "Copyright 2014-2019 Dean Jackson" 64 | 65 | __all__ = [ 66 | "Variables", 67 | "Workflow", 68 | "Workflow3", 69 | "manager", 70 | "PasswordNotFound", 71 | "KeychainError", 72 | "ICON_ACCOUNT", 73 | "ICON_BURN", 74 | "ICON_CLOCK", 75 | "ICON_COLOR", 76 | "ICON_COLOUR", 77 | "ICON_EJECT", 78 | "ICON_ERROR", 79 | "ICON_FAVORITE", 80 | "ICON_FAVOURITE", 81 | "ICON_GROUP", 82 | "ICON_HELP", 83 | "ICON_HOME", 84 | "ICON_INFO", 85 | "ICON_NETWORK", 86 | "ICON_NOTE", 87 | "ICON_SETTINGS", 88 | "ICON_SWIRL", 89 | "ICON_SWITCH", 90 | "ICON_SYNC", 91 | "ICON_TRASH", 92 | "ICON_USER", 93 | "ICON_WARNING", 94 | "ICON_WEB", 95 | "MATCH_ALL", 96 | "MATCH_ALLCHARS", 97 | "MATCH_ATOM", 98 | "MATCH_CAPITALS", 99 | "MATCH_INITIALS", 100 | "MATCH_INITIALS_CONTAIN", 101 | "MATCH_INITIALS_STARTSWITH", 102 | "MATCH_STARTSWITH", 103 | "MATCH_SUBSTRING", 104 | ] 105 | -------------------------------------------------------------------------------- /.site-packages/workflow/version: -------------------------------------------------------------------------------- 1 | 1.40.0 -------------------------------------------------------------------------------- /7D9DF57A-5DF9-5DB9-AB88-88DAC6AD7FB1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jessedobbelaere/alfred-iterm-profiles-workflow/b6b44e42b1a9c9dff6b4b4fccadcbea1210b6eea/7D9DF57A-5DF9-5DB9-AB88-88DAC6AD7FB1.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # iTerm Profiles Workflow for [Alfred](http://www.alfredapp.com) 2 | 3 | [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat)](http://makeapullrequest.com) 4 | 5 | > Search through your iTerm profiles using Alfred and easily open one. Extremely useful if you have a lot of profiles, e.g. with an SSH command for each server. 6 | 7 | ## 🔧 Installation 8 | 9 | **[Download workflow here](https://github.com/jessedobbelaere/alfred-iterm-profiles-workflow/releases)** 10 | 11 | ## ⚙️ Usage 12 | 13 | 1. Enter keyword `profile` in Alfred, followed by a searchquery to find the profile you need. 14 | 2. Hit and iTerm will open your profile 15 | 16 | ![Preview](https://i.imgur.com/TKlKLct.png) 17 | -------------------------------------------------------------------------------- /__version__.py: -------------------------------------------------------------------------------- 1 | __version__ = "2.0.0" 2 | 3 | if __name__ == "__main__": 4 | print(__version__) 5 | -------------------------------------------------------------------------------- /build-workflow-distributable.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | 4 | # Build the workflow 5 | zip -r alfred-iterm-profiles-workflow.alfredworkflow .site-packages/* 6 | zip -r alfred-iterm-profiles-workflow.alfredworkflow lib/* 7 | zip -r alfred-iterm-profiles-workflow.alfredworkflow *.py 8 | zip -r alfred-iterm-profiles-workflow.alfredworkflow *.png 9 | zip -r alfred-iterm-profiles-workflow.alfredworkflow README.md 10 | zip -r alfred-iterm-profiles-workflow.alfredworkflow icon.png 11 | zip -r alfred-iterm-profiles-workflow.alfredworkflow info.plist 12 | -------------------------------------------------------------------------------- /entrypoint.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # encoding: utf-8 3 | from __future__ import annotations 4 | 5 | import os 6 | import sys 7 | 8 | # setup access to the local .site-packages 9 | sys.path.insert(0, os.path.dirname(__file__) + "/.site-packages") # noqa 10 | 11 | 12 | from workflow import Workflow3, ICON_WARNING, MATCH_SUBSTRING 13 | from lib import biplist 14 | 15 | 16 | def main(wf: Workflow3): 17 | try: 18 | # Fetch cached profiles 19 | all_profiles = wf.cached_data('profiles', read_iterm_profiles, max_age=30) 20 | 21 | # Query argument Ensure `query` is initialised 22 | query = None 23 | if len(wf.args): 24 | query = wf.args[0] 25 | 26 | # Filter profiles by query 27 | profiles = wf.filter(query, all_profiles, filter_key_for_profile, match_on=MATCH_SUBSTRING) 28 | 29 | if not profiles: 30 | wf.add_item('No profile matches', icon=ICON_WARNING) 31 | 32 | profiles.sort(key=sort_key_for_profile) 33 | for profile in profiles: 34 | wf.add_item(title=profile['name'], 35 | subtitle=((str(profile['tags']) + ' ') if profile['tags'] else '') + profile['command'], 36 | arg=profile['name'], 37 | valid=True, 38 | icon=profile['icon']) 39 | 40 | wf.send_feedback() 41 | except Exception as e: 42 | wf.logger.exception(e) 43 | raise 44 | 45 | def read_iterm_profiles(): 46 | # Read iTerm's preferences file 47 | iTermPreferencesPath = os.path.join(os.environ["HOME"], "Library", "Preferences", "com.googlecode.iterm2.plist") 48 | plist = biplist.readPlist(iTermPreferencesPath) 49 | # Extract profile data from plist 50 | profiles = [] 51 | for nb in plist['New Bookmarks']: 52 | profiles.append({ 53 | 'name': nb.get('Name'), 54 | 'command': nb.get('Command'), 55 | 'icon': nb.get('Custom Icon Path'), 56 | 'tags': nb.get('Tags') 57 | }) 58 | 59 | return profiles 60 | 61 | def filter_key_for_profile(profile): 62 | return profile['name'] + ' ' + str(profile['tags']) 63 | 64 | def sort_key_for_profile(profile): 65 | return profile['name'] 66 | 67 | if __name__ == "__main__": 68 | # Create a global `Workflow3` object 69 | wf = Workflow3() 70 | wf.logger.info(__name__) 71 | # Call your entry function via `Workflow3.run()` to enable its 72 | # helper functions, like exception catching, ARGV normalization, 73 | # magic arguments etc. 74 | wf.run(main) 75 | -------------------------------------------------------------------------------- /icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jessedobbelaere/alfred-iterm-profiles-workflow/b6b44e42b1a9c9dff6b4b4fccadcbea1210b6eea/icon.png -------------------------------------------------------------------------------- /info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | bundleid 6 | re.jessedobbelae.itermprofile 7 | category 8 | Productivity 9 | connections 10 | 11 | 7D9DF57A-5DF9-5DB9-AB88-88DAC6AD7FB1 12 | 13 | 14 | destinationuid 15 | 5ACF9B16-49E7-41E0-925D-A0C40D5DEBED 16 | modifiers 17 | 0 18 | modifiersubtext 19 | 20 | vitoclose 21 | 22 | 23 | 24 | 25 | createdby 26 | Jesse Dobbelaere 27 | description 28 | Easily start an iTerm profile straight from Alfred 29 | disabled 30 | 31 | name 32 | Open iTerm Profile 33 | objects 34 | 35 | 36 | config 37 | 38 | applescript 39 | on alfred_script(q) 40 | 41 | tell application "System Events" 42 | -- some versions might identify as "iTerm2" instead of "iTerm" 43 | set isRunning to (exists (processes where name is "iTerm")) or (exists (processes where name is "iTerm2")) 44 | end tell 45 | 46 | tell application "iTerm" 47 | activate 48 | 49 | if not (isRunning) then 50 | delay 0.5 51 | close the current window 52 | create window with profile q 53 | end if 54 | 55 | set hasNoWindows to ((count of windows) is 0) 56 | if isRunning and hasNoWindows then 57 | delay 0.5 58 | close the current window 59 | create window with profile q 60 | end if 61 | 62 | select first window 63 | 64 | tell the first window 65 | if isRunning and hasNoWindows is false then 66 | create tab with profile q 67 | end if 68 | end tell 69 | end tell 70 | 71 | end alfred_script 72 | cachescript 73 | 74 | 75 | type 76 | alfred.workflow.action.applescript 77 | uid 78 | 5ACF9B16-49E7-41E0-925D-A0C40D5DEBED 79 | version 80 | 1 81 | 82 | 83 | config 84 | 85 | alfredfiltersresults 86 | 87 | alfredfiltersresultsmatchmode 88 | 0 89 | argumenttreatemptyqueryasnil 90 | 91 | argumenttrimmode 92 | 0 93 | argumenttype 94 | 1 95 | escaping 96 | 0 97 | keyword 98 | profile 99 | queuedelaycustom 100 | 3 101 | queuedelayimmediatelyinitially 102 | 103 | queuedelaymode 104 | 0 105 | queuemode 106 | 1 107 | runningsubtext 108 | Please Wait 109 | script 110 | 111 | scriptargtype 112 | 1 113 | scriptfile 114 | entrypoint.py 115 | subtext 116 | Find and open an iTerm profile 117 | title 118 | Enter an iTerm profile name 119 | type 120 | 8 121 | withspace 122 | 123 | 124 | type 125 | alfred.workflow.input.scriptfilter 126 | uid 127 | 7D9DF57A-5DF9-5DB9-AB88-88DAC6AD7FB1 128 | version 129 | 3 130 | 131 | 132 | readme 133 | Search through your iTerm profiles using Alfred and easily open one. Extremely useful if you have a lot of profiles, e.g. with an SSH command for each server. 134 | uidata 135 | 136 | 5ACF9B16-49E7-41E0-925D-A0C40D5DEBED 137 | 138 | xpos 139 | 435 140 | ypos 141 | 120 142 | 143 | 7D9DF57A-5DF9-5DB9-AB88-88DAC6AD7FB1 144 | 145 | xpos 146 | 210 147 | ypos 148 | 120 149 | 150 | 151 | variablesdontexport 152 | 153 | version 154 | 2.0.0 155 | webaddress 156 | https://github.com/jessedobbelaere/alfred-iterm-profiles-workflow 157 | 158 | 159 | -------------------------------------------------------------------------------- /lib/biplist-1.0.3.dist-info/AUTHORS: -------------------------------------------------------------------------------- 1 | Andrew Wooster (andrew@planetaryscale.com) 2 | 3 | Ported to Python 3 by Kevin Kelley (kelleyk@kelleyk.net) 4 | -------------------------------------------------------------------------------- /lib/biplist-1.0.3.dist-info/INSTALLER: -------------------------------------------------------------------------------- 1 | pip 2 | -------------------------------------------------------------------------------- /lib/biplist-1.0.3.dist-info/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2010, Andrew Wooster 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, 8 | this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * Neither the name of biplist nor the names of its contributors may be 13 | used to endorse or promote products derived from this software without 14 | specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 20 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | -------------------------------------------------------------------------------- /lib/biplist-1.0.3.dist-info/METADATA: -------------------------------------------------------------------------------- 1 | Metadata-Version: 2.1 2 | Name: biplist 3 | Version: 1.0.3 4 | Summary: biplist is a library for reading/writing binary plists. 5 | Home-page: https://bitbucket.org/wooster/biplist 6 | Download-URL: https://bitbucket.org/wooster/biplist/downloads/biplist-1.0.3.tar.gz 7 | Author: Andrew Wooster 8 | Author-email: andrew@planetaryscale.com 9 | License: BSD 10 | Platform: UNKNOWN 11 | Classifier: Development Status :: 5 - Production/Stable 12 | Classifier: Intended Audience :: Developers 13 | Classifier: License :: OSI Approved :: BSD License 14 | Classifier: Operating System :: OS Independent 15 | Classifier: Programming Language :: Python 16 | Classifier: Topic :: Software Development :: Libraries :: Python Modules 17 | Classifier: Topic :: Text Processing :: Markup 18 | License-File: LICENSE 19 | License-File: AUTHORS 20 | 21 | `biplist` is a binary plist parser/generator for Python. 22 | 23 | Binary Property List (plist) files provide a faster and smaller serialization 24 | format for property lists on OS X. This is a library for generating binary 25 | plists which can be read by OS X, iOS, or other clients. 26 | 27 | This module requires Python 2.6 or higher or Python 3.4 or higher. 28 | 29 | -------------------------------------------------------------------------------- /lib/biplist-1.0.3.dist-info/RECORD: -------------------------------------------------------------------------------- 1 | biplist-1.0.3.dist-info/AUTHORS,sha256=ohIvnBZ_jr_4CAO6PvfK22HiA-ZiMM_2hHBJKe-g-7Q,101 2 | biplist-1.0.3.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 3 | biplist-1.0.3.dist-info/LICENSE,sha256=aO5PxXo1YY9t7RwJ8_YhZTC5RAc0voBcK1BM9V0kLjQ,1510 4 | biplist-1.0.3.dist-info/METADATA,sha256=qXXZXMAJ9MFl58rGVNFhHYooYootAEtxqgVCvi4lUPo,1085 5 | biplist-1.0.3.dist-info/RECORD,, 6 | biplist-1.0.3.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 7 | biplist-1.0.3.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92 8 | biplist-1.0.3.dist-info/top_level.txt,sha256=TT2vZtYziYVpLawg8KXvf6vAOlwDVwsHk0OpMih9Mk8,8 9 | biplist/__init__.py,sha256=GEagv9tNCJiD45H_t8Qp_dfqq-fKYLO122HdKzux2Tc,37313 10 | biplist/__pycache__/__init__.cpython-39.pyc,, 11 | -------------------------------------------------------------------------------- /lib/biplist-1.0.3.dist-info/REQUESTED: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jessedobbelaere/alfred-iterm-profiles-workflow/b6b44e42b1a9c9dff6b4b4fccadcbea1210b6eea/lib/biplist-1.0.3.dist-info/REQUESTED -------------------------------------------------------------------------------- /lib/biplist-1.0.3.dist-info/WHEEL: -------------------------------------------------------------------------------- 1 | Wheel-Version: 1.0 2 | Generator: bdist_wheel (0.37.1) 3 | Root-Is-Purelib: true 4 | Tag: py3-none-any 5 | 6 | -------------------------------------------------------------------------------- /lib/biplist-1.0.3.dist-info/top_level.txt: -------------------------------------------------------------------------------- 1 | biplist 2 | --------------------------------------------------------------------------------