├── Dockerfile ├── README.md └── mid ├── Dockerfile └── python.snippets /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM duckll/ctf-box:mid 2 | 3 | # apt 4 | RUN apt update \ 5 | && apt install -y \ 6 | automake \ 7 | bison \ 8 | libglib2.0-dev \ 9 | libtool-bin \ 10 | libpcre++-dev \ 11 | nmap \ 12 | p7zip-full \ 13 | pcregrep \ 14 | 15 | # pip 16 | && pip2 install \ 17 | angr \ 18 | # distorm3 \ 19 | gmpy \ 20 | # openpyxl \ 21 | pycrypto \ 22 | Pillow \ 23 | # sympy \ 24 | # ujson \ 25 | xortool \ 26 | # yara-python \ 27 | 28 | 29 | # afl 30 | && cd /tmp \ 31 | && git clone https://github.com/google/AFL.git --depth 1 \ 32 | && cd AFL \ 33 | && make \ 34 | && make install \ 35 | && cd ./qemu_mode \ 36 | && ./build_qemu_support.sh \ 37 | 38 | # binwalk 39 | && cd /tmp \ 40 | && git clone https://github.com/devttys0/binwalk.git --depth 1 \ 41 | && cd ./binwalk \ 42 | && ./setup.py install \ 43 | 44 | # pintool 45 | # && wget http://software.intel.com/sites/landingpage/pintool/downloads/pin-3.4-97438-gf90d1f746-gcc-linux.tar.gz \ 46 | # && tar -zxvf pin-3.4-97438-gf90d1f746-gcc-linux.tar.gz \ 47 | # && rm pin-3.4-97438-gf90d1f746-gcc-linux.tar.gz \ 48 | # && mv pin-3.4-97438-gf90d1f746-gcc-linux pin \ 49 | # && echo 'export PATH="/pin:$PATH"' >> ~/.bashrc \ 50 | # && cd pin/source/tools \ 51 | # && make \ 52 | 53 | # volatility 54 | # && cd / \ 55 | # && git clone https://github.com/volatilityfoundation/volatility.git \ 56 | # && cd ./volatility \ 57 | # && python setup.py install \ 58 | # && cd ../ \ 59 | # && rm -rf ./volatility \ 60 | 61 | # cleanup 62 | && apt clean \ 63 | && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* 64 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Feature 2 | 1. Base on ubuntu 18.04 3 | 1. Latest version tools 4 | 1. Support multiarch 5 | 6 | # Install 7 | 1. docker pull duckll/ctf-box 8 | 1. docker run -idt --name ctf --privileged --security-opt seccomp:unconfined duckll/ctf-box 9 | 10 | # Usage 11 | 1. docker start ctf 12 | 1. docker exec -it ctf tmux 13 | 14 | # Include 15 | 1. ipython 16 | 1. pwntools 17 | 1. gef 18 | 1. pwn-gdb 19 | 1. qemu 20 | 1. one_gadget 21 | 1. heapinfo 22 | 1. seccomp-tools 23 | 1. afl 24 | 1. binwalk 25 | 1. angr 26 | -------------------------------------------------------------------------------- /mid/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM duckll/base 2 | 3 | COPY ./python.snippets /root/.config/nvim/plugged/vim-snippets/UltiSnips 4 | 5 | # apt 6 | RUN dpkg --add-architecture i386 \ 7 | && apt update \ 8 | && apt -y install \ 9 | cmake \ 10 | g++ \ 11 | gdb-multiarch \ 12 | libc6:i386 \ 13 | ltrace \ 14 | make \ 15 | nasm \ 16 | python-pip \ 17 | qemu \ 18 | ruby-dev \ 19 | strace \ 20 | 21 | # pip2 22 | && pip2 install \ 23 | ipython \ 24 | pwntools \ 25 | 26 | # pip3 27 | && pip3 install \ 28 | capstone \ 29 | keystone-engine \ 30 | ropper \ 31 | unicorn \ 32 | 33 | # rubypwn 34 | && gem install \ 35 | one_gadget \ 36 | seccomp-tools \ 37 | heapinfo \ 38 | && echo 'for dir in $HOME/.gem/ruby/*; do' >> ~/.bashrc \ 39 | && echo ' [ -d "$dir/bin" ] && PATH="${dir}/bin:${PATH}"' >> ~/.bashrc \ 40 | && echo 'done' >> ~/.bashrc \ 41 | 42 | # gdb 43 | && wget -q -O- https://github.com/hugsy/gef/raw/master/scripts/gef.sh | sh \ 44 | && git clone https://github.com/scwuaptx/Pwngdb.git --depth 1 ~/Pwngdb \ 45 | && cat ~/Pwngdb/.gdbinit >> ~/.gdbinit \ 46 | 47 | # cleanup 48 | && apt clean \ 49 | && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* 50 | -------------------------------------------------------------------------------- /mid/python.snippets: -------------------------------------------------------------------------------- 1 | priority -50 2 | 3 | ########################################################################### 4 | # TEXTMATE SNIPPETS # 5 | ########################################################################### 6 | 7 | snippet pwn 8 | from pwn import * 9 | context.arch='amd64' 10 | 11 | elf=ELF('$1') 12 | # libc=ELF('./libc.so.6') 13 | env={'LD_PRELOAD':'./libc.so.6'} 14 | 15 | io=process('${1:./a.out}') 16 | # io=remote('${2:ip}',${3:port}) 17 | $0 18 | 19 | io.interactive() 20 | endsnippet 21 | 22 | #! header 23 | snippet #! "Shebang header for python scripts" b 24 | #!/usr/bin/env python 25 | # -*- coding: utf-8 -*- 26 | $0 27 | endsnippet 28 | 29 | snippet ifmain "ifmain" b 30 | if __name__ == `!p snip.rv = get_quoting_style(snip)`__main__`!p snip.rv = get_quoting_style(snip)`: 31 | ${1:${VISUAL:main()}} 32 | endsnippet 33 | 34 | snippet with "with" b 35 | with ${1:expr}`!p snip.rv = " as " if t[2] else ""`${2:var}: 36 | ${3:${VISUAL:pass}} 37 | $0 38 | endsnippet 39 | 40 | snippet for "for loop" b 41 | for ${1:item} in ${2:iterable}: 42 | ${3:${VISUAL:pass}} 43 | endsnippet 44 | 45 | ########## 46 | # COMMON # 47 | ########## 48 | 49 | # The smart def and smart class snippets use a global option called 50 | # "g:ultisnips_python_style" which, if set to "doxygen" will use doxygen 51 | # style comments in docstrings. 52 | 53 | global !p 54 | 55 | NORMAL = 0x1 56 | DOXYGEN = 0x2 57 | SPHINX = 0x3 58 | GOOGLE = 0x4 59 | NUMPY = 0x5 60 | JEDI = 0x6 61 | 62 | SINGLE_QUOTES = "'" 63 | DOUBLE_QUOTES = '"' 64 | 65 | 66 | class Arg(object): 67 | def __init__(self, arg): 68 | self.arg = arg 69 | self.name = arg.split('=')[0].strip() 70 | 71 | def __str__(self): 72 | return self.name 73 | 74 | def __unicode__(self): 75 | return self.name 76 | 77 | def is_kwarg(self): 78 | return '=' in self.arg 79 | 80 | 81 | def get_args(arglist): 82 | args = [Arg(arg) for arg in arglist.split(',') if arg] 83 | args = [arg for arg in args if arg.name != 'self'] 84 | 85 | return args 86 | 87 | 88 | def get_quoting_style(snip): 89 | style = snip.opt("g:ultisnips_python_quoting_style", "double") 90 | if style == 'single': 91 | return SINGLE_QUOTES 92 | return DOUBLE_QUOTES 93 | 94 | def triple_quotes(snip): 95 | style = snip.opt("g:ultisnips_python_triple_quoting_style") 96 | if not style: 97 | return get_quoting_style(snip) * 3 98 | return (SINGLE_QUOTES if style == 'single' else DOUBLE_QUOTES) * 3 99 | 100 | def triple_quotes_handle_trailing(snip, quoting_style): 101 | """ 102 | Generate triple quoted strings and handle any trailing quote char, 103 | which might be there from some autoclose/autopair plugin, 104 | i.e. when expanding ``"|"``. 105 | """ 106 | if not snip.c: 107 | # Do this only once, otherwise the following error would happen: 108 | # RuntimeError: The snippets content did not converge: … 109 | _, col = vim.current.window.cursor 110 | line = vim.current.line 111 | 112 | # Handle already existing quote chars after the trigger. 113 | _ret = quoting_style * 3 114 | while True: 115 | try: 116 | nextc = line[col] 117 | except IndexError: 118 | break 119 | if nextc == quoting_style and len(_ret): 120 | _ret = _ret[1:] 121 | col = col+1 122 | else: 123 | break 124 | snip.rv = _ret 125 | else: 126 | snip.rv = snip.c 127 | 128 | def get_style(snip): 129 | style = snip.opt("g:ultisnips_python_style", "normal") 130 | 131 | if style == "doxygen": return DOXYGEN 132 | elif style == "sphinx": return SPHINX 133 | elif style == "google": return GOOGLE 134 | elif style == "numpy": return NUMPY 135 | elif style == "jedi": return JEDI 136 | else: return NORMAL 137 | 138 | 139 | def format_arg(arg, style): 140 | if style == DOXYGEN: 141 | return "@param %s TODO" % arg 142 | elif style == SPHINX: 143 | return ":param %s: TODO" % arg 144 | elif style == NORMAL: 145 | return ":%s: TODO" % arg 146 | elif style == GOOGLE: 147 | return "%s (TODO): TODO" % arg 148 | elif style == JEDI: 149 | return ":type %s: TODO" % arg 150 | elif style == NUMPY: 151 | return "%s : TODO" % arg 152 | 153 | 154 | def format_return(style): 155 | if style == DOXYGEN: 156 | return "@return: TODO" 157 | elif style in (NORMAL, SPHINX, JEDI): 158 | return ":returns: TODO" 159 | elif style == GOOGLE: 160 | return "Returns: TODO" 161 | 162 | 163 | def write_docstring_args(args, snip): 164 | if not args: 165 | snip.rv += ' {0}'.format(triple_quotes(snip)) 166 | return 167 | 168 | snip.rv += '\n' + snip.mkline('', indent='') 169 | 170 | style = get_style(snip) 171 | 172 | if style == GOOGLE: 173 | write_google_docstring_args(args, snip) 174 | elif style == NUMPY: 175 | write_numpy_docstring_args(args, snip) 176 | else: 177 | for arg in args: 178 | snip += format_arg(arg, style) 179 | 180 | 181 | def write_google_docstring_args(args, snip): 182 | kwargs = [arg for arg in args if arg.is_kwarg()] 183 | args = [arg for arg in args if not arg.is_kwarg()] 184 | 185 | if args: 186 | snip += "Args:" 187 | snip.shift() 188 | for arg in args: 189 | snip += format_arg(arg, GOOGLE) 190 | snip.unshift() 191 | snip.rv += '\n' + snip.mkline('', indent='') 192 | 193 | if kwargs: 194 | snip += "Kwargs:" 195 | snip.shift() 196 | for kwarg in kwargs: 197 | snip += format_arg(kwarg, GOOGLE) 198 | snip.unshift() 199 | snip.rv += '\n' + snip.mkline('', indent='') 200 | 201 | 202 | def write_numpy_docstring_args(args, snip): 203 | if args: 204 | snip += "Parameters" 205 | snip += "----------" 206 | 207 | kwargs = [arg for arg in args if arg.is_kwarg()] 208 | args = [arg for arg in args if not arg.is_kwarg()] 209 | 210 | if args: 211 | for arg in args: 212 | snip += format_arg(arg, NUMPY) 213 | if kwargs: 214 | for kwarg in kwargs: 215 | snip += format_arg(kwarg, NUMPY) + ', optional' 216 | snip.rv += '\n' + snip.mkline('', indent='') 217 | 218 | 219 | def write_init_body(args, parents, snip): 220 | parents = [p.strip() for p in parents.split(",")] 221 | parents = [p for p in parents if p != 'object'] 222 | 223 | for p in parents: 224 | snip += p + ".__init__(self)" 225 | 226 | if parents: 227 | snip.rv += '\n' + snip.mkline('', indent='') 228 | 229 | for arg in args: 230 | snip += "self._%s = %s" % (arg, arg) 231 | 232 | 233 | def write_slots_args(args, snip): 234 | args = ['"_%s"' % arg for arg in args] 235 | snip += '__slots__ = (%s,)' % ', '.join(args) 236 | 237 | 238 | def write_function_docstring(t, snip): 239 | """ 240 | Writes a function docstring with the current style. 241 | 242 | :param t: The values of the placeholders 243 | :param snip: UltiSnips.TextObjects.SnippetUtil object instance 244 | """ 245 | snip.rv = "" 246 | snip >> 1 247 | 248 | args = get_args(t[2]) 249 | if args: 250 | write_docstring_args(args, snip) 251 | 252 | style = get_style(snip) 253 | 254 | if style == NUMPY: 255 | snip += 'Returns' 256 | snip += '-------' 257 | snip += 'TODO' 258 | else: 259 | snip += format_return(style) 260 | snip.rv += '\n' + snip.mkline('', indent='') 261 | snip += triple_quotes(snip) 262 | 263 | def get_dir_and_file_name(snip): 264 | return os.getcwd().split(os.sep)[-1] + '.' + snip.basename 265 | 266 | endglobal 267 | 268 | ######################################## 269 | # Class & Special Method Name Snippets # 270 | ######################################## 271 | 272 | snippet class "class with docstrings" b 273 | class ${1:MyClass}(${2:object}): 274 | 275 | `!p snip.rv = triple_quotes(snip)`${3:Docstring for $1. }`!p snip.rv = triple_quotes(snip)` 276 | 277 | def __init__(self$4): 278 | `!p snip.rv = triple_quotes(snip)`${5:TODO: to be defined1.}`!p 279 | snip.rv = "" 280 | snip >> 2 281 | 282 | args = get_args(t[4]) 283 | 284 | write_docstring_args(args, snip) 285 | if args: 286 | snip.rv += '\n' + snip.mkline('', indent='') 287 | snip += '{0}'.format(triple_quotes(snip)) 288 | 289 | write_init_body(args, t[2], snip) 290 | ` 291 | $0 292 | endsnippet 293 | 294 | 295 | snippet slotclass "class with slots and docstrings" b 296 | class ${1:MyClass}(${2:object}): 297 | 298 | `!p snip.rv = triple_quotes(snip)`${3:Docstring for $1. }`!p snip.rv = triple_quotes(snip)` 299 | `!p 300 | snip >> 1 301 | args = get_args(t[4]) 302 | write_slots_args(args, snip) 303 | ` 304 | 305 | def __init__(self$4): 306 | `!p snip.rv = triple_quotes(snip)`${5:TODO: to be defined.}`!p 307 | snip.rv = "" 308 | snip >> 2 309 | 310 | args = get_args(t[4]) 311 | 312 | write_docstring_args(args, snip) 313 | if args: 314 | snip.rv += '\n' + snip.mkline('', indent='') 315 | snip += triple_quotes(snip) 316 | 317 | write_init_body(args, t[2], snip) 318 | ` 319 | $0 320 | endsnippet 321 | 322 | 323 | snippet contain "methods for emulating a container type" b 324 | def __len__(self): 325 | ${1:pass} 326 | 327 | def __getitem__(self, key): 328 | ${2:pass} 329 | 330 | def __setitem__(self, key, value): 331 | ${3:pass} 332 | 333 | def __delitem__(self, key): 334 | ${4:pass} 335 | 336 | def __iter__(self): 337 | ${5:pass} 338 | 339 | def __reversed__(self): 340 | ${6:pass} 341 | 342 | def __contains__(self, item): 343 | ${7:pass} 344 | endsnippet 345 | 346 | 347 | snippet context "context manager methods" b 348 | def __enter__(self): 349 | ${1:pass} 350 | 351 | def __exit__(self, exc_type, exc_value, traceback): 352 | ${2:pass} 353 | endsnippet 354 | 355 | 356 | snippet attr "methods for customizing attribute access" b 357 | def __getattr__(self, name): 358 | ${1:pass} 359 | 360 | def __setattr__(self, name, value): 361 | ${2:pass} 362 | 363 | def __delattr__(self, name): 364 | ${3:pass} 365 | endsnippet 366 | 367 | 368 | snippet desc "methods implementing descriptors" b 369 | def __get__(self, instance, owner): 370 | ${1:pass} 371 | 372 | def __set__(self, instance, value): 373 | ${2:pass} 374 | 375 | def __delete__(self, instance): 376 | ${3:pass} 377 | endsnippet 378 | 379 | 380 | snippet cmp "methods implementing rich comparison" 381 | def __eq__(self, other): 382 | ${1:pass} 383 | 384 | def __ne__(self, other): 385 | ${2:pass} 386 | 387 | def __lt__(self, other): 388 | ${3:pass} 389 | 390 | def __le__(self, other): 391 | ${4:pass} 392 | 393 | def __gt__(self, other): 394 | ${5:pass} 395 | 396 | def __ge__(self, other): 397 | ${6:pass} 398 | 399 | def __cmp__(self, other): 400 | ${7:pass} 401 | endsnippet 402 | 403 | 404 | snippet repr "methods implementing string representation" 405 | def __repr__(self): 406 | ${1:pass} 407 | 408 | def __str__(self): 409 | ${2:pass} 410 | 411 | def __unicode__(self): 412 | ${3:pass} 413 | endsnippet 414 | 415 | 416 | # note: reflected operands and augmented arithmeitc assignements have been 417 | # intentionally ommited to reduce verbosity. 418 | snippet numeric "methods for emulating a numeric type" b 419 | def __add__(self, other): 420 | ${1:pass} 421 | 422 | def __sub__(self, other): 423 | ${2:pass} 424 | 425 | def __mul__(self, other): 426 | ${3:pass} 427 | 428 | def __div__(self, other): 429 | ${4:pass} 430 | 431 | def __truediv__(self, other): 432 | ${5:pass} 433 | 434 | def __floordiv__(self, other): 435 | ${6:pass} 436 | 437 | 438 | def __mod__(self, other): 439 | ${7:pass} 440 | 441 | def __divmod__(self, other): 442 | ${8:pass} 443 | 444 | def __pow__(self, other): 445 | ${9:pass} 446 | 447 | 448 | def __lshift__(self, other): 449 | ${10:pass} 450 | 451 | def __rshift__(self, other): 452 | ${11:pass} 453 | 454 | def __and__(self, other): 455 | ${12:pass} 456 | 457 | def __xor__(self, other): 458 | ${13:pass} 459 | 460 | def __or__(self, other): 461 | ${14:pass} 462 | 463 | 464 | def __neg__(self): 465 | ${15:pass} 466 | 467 | def __pos__(self): 468 | ${16:pass} 469 | 470 | def __abs__(self): 471 | ${17:pass} 472 | 473 | def __invert__(self): 474 | ${18:pass} 475 | 476 | 477 | def __complex__(self): 478 | ${19:pass} 479 | 480 | def __int__(self): 481 | ${20:pass} 482 | 483 | def __long__(self): 484 | ${21:pass} 485 | 486 | def __float__(self): 487 | ${22:pass} 488 | 489 | 490 | def __oct__(self): 491 | ${22:pass} 492 | 493 | def __hex__(self): 494 | ${23:pass} 495 | 496 | 497 | def __index__(self): 498 | ${24:pass} 499 | 500 | def __coerce__(self, other): 501 | ${25:pass} 502 | endsnippet 503 | 504 | snippet deff 505 | def ${1:fname}(`!p snip.rv = vim.eval('indent(".") ? "self" : ""')`$2): 506 | $0 507 | endsnippet 508 | 509 | snippet def "function with docstrings" b 510 | def ${1:function}(`!p 511 | if snip.indent: 512 | snip.rv = 'self' + (", " if len(t[2]) else "")`${2:arg1}): 513 | `!p snip.rv = triple_quotes(snip)`${4:TODO: Docstring for $1.}`!p 514 | write_function_docstring(t, snip) ` 515 | ${5:${VISUAL:pass}} 516 | endsnippet 517 | 518 | 519 | snippet defc "class method with docstrings" b 520 | @classmethod 521 | def ${1:function}(`!p 522 | if snip.indent: 523 | snip.rv = 'cls' + (", " if len(t[2]) else "")`${2:arg1}): 524 | `!p snip.rv = triple_quotes(snip)`${4:TODO: Docstring for $1.}`!p 525 | write_function_docstring(t, snip) ` 526 | ${5:${VISUAL:pass}} 527 | endsnippet 528 | 529 | 530 | snippet defs "static method with docstrings" b 531 | @staticmethod 532 | def ${1:function}(${2:arg1}): 533 | `!p snip.rv = triple_quotes(snip)`${4:TODO: Docstring for $1.}`!p 534 | write_function_docstring(t, snip) ` 535 | ${5:${VISUAL:pass}} 536 | endsnippet 537 | 538 | 539 | # doesn't expand when there is a word in front 540 | snippet /(^|(?<=\W))\./ "self." r 541 | self. 542 | endsnippet 543 | 544 | snippet from "from module import name" b 545 | from ${1:module} import ${2:Stuff} 546 | endsnippet 547 | 548 | 549 | ############## 550 | # PROPERTIES # 551 | ############## 552 | snippet roprop "Read Only Property" b 553 | @property 554 | def ${1:name}(self): 555 | ${2:return self._$1}$0 556 | endsnippet 557 | 558 | snippet rwprop "Read write property" b 559 | def ${1:name}(): 560 | `!p snip.rv = triple_quotes(snip) if t[2] else '' 561 | `${2:TODO: Docstring for $1.}`!p 562 | if t[2]: 563 | snip >> 1 564 | 565 | style = get_style(snip) 566 | snip.rv += '\n' + snip.mkline('', indent='') 567 | snip += format_return(style) 568 | snip.rv += '\n' + snip.mkline('', indent='') 569 | snip += triple_quotes(snip) 570 | else: 571 | snip.rv = ""` 572 | def fget(self): 573 | return self._$1$0 574 | 575 | def fset(self, value): 576 | self._$1 = value 577 | return locals() 578 | 579 | $1 = property(**$1(), doc=$1.__doc__) 580 | endsnippet 581 | 582 | 583 | #################### 584 | # If / Else / Elif # 585 | #################### 586 | snippet if "If" b 587 | if ${1:condition}: 588 | ${2:${VISUAL:pass}} 589 | endsnippet 590 | 591 | snippet ife "If / Else" b 592 | if ${1:condition}: 593 | ${2:${VISUAL:pass}} 594 | else: 595 | ${3:pass} 596 | endsnippet 597 | 598 | snippet ifee "If / Elif / Else" b 599 | if ${1:condition}: 600 | ${2:${VISUAL:pass}} 601 | elif ${3:condition}: 602 | ${4:pass} 603 | else: 604 | ${5:pass} 605 | endsnippet 606 | 607 | 608 | ########################## 609 | # Try / Except / Finally # 610 | ########################## 611 | snippet try "Try / Except" b 612 | try: 613 | ${1:${VISUAL:pass}} 614 | except ${2:Exception} as ${3:e}: 615 | ${4:raise $3} 616 | endsnippet 617 | 618 | snippet trye "Try / Except / Else" b 619 | try: 620 | ${1:${VISUAL:pass}} 621 | except ${2:Exception} as ${3:e}: 622 | ${4:raise $3} 623 | else: 624 | ${5:pass} 625 | endsnippet 626 | 627 | snippet tryf "Try / Except / Finally" b 628 | try: 629 | ${1:${VISUAL:pass}} 630 | except ${2:Exception} as ${3:e}: 631 | ${4:raise $3} 632 | finally: 633 | ${5:pass} 634 | endsnippet 635 | 636 | snippet tryef "Try / Except / Else / Finally" b 637 | try: 638 | ${1:${VISUAL:pass}} 639 | except${2: ${3:Exception} as ${4:e}}: 640 | ${5:raise} 641 | else: 642 | ${6:pass} 643 | finally: 644 | ${7:pass} 645 | endsnippet 646 | 647 | 648 | ###################### 649 | # Assertions & Tests # 650 | ###################### 651 | 652 | snippet ae "Assert equal" b 653 | self.assertEqual(${1:${VISUAL:first}},${2:second}) 654 | endsnippet 655 | 656 | snippet at "Assert True" b 657 | self.assertTrue(${1:${VISUAL:expression}}) 658 | endsnippet 659 | 660 | snippet af "Assert False" b 661 | self.assertFalse(${1:${VISUAL:expression}}) 662 | endsnippet 663 | 664 | snippet aae "Assert almost equal" b 665 | self.assertAlmostEqual(${1:${VISUAL:first}},${2:second}) 666 | endsnippet 667 | 668 | snippet ar "Assert raises" b 669 | self.assertRaises(${1:exception}, ${2:${VISUAL:func}}${3/.+/, /}${3:arguments}) 670 | endsnippet 671 | 672 | snippet an "Assert is None" b 673 | self.assertIsNone(${1:${VISUAL:expression}}) 674 | endsnippet 675 | 676 | snippet ann "Assert is not None" b 677 | self.assertIsNotNone(${1:${VISUAL:expression}}) 678 | endsnippet 679 | 680 | snippet testcase "pyunit testcase" b 681 | class Test${1:Class}(${2:unittest.TestCase}): 682 | 683 | `!p snip.rv = triple_quotes(snip)`${3:Test case docstring.}`!p snip.rv = triple_quotes(snip)` 684 | 685 | def setUp(self): 686 | ${4:pass} 687 | 688 | def tearDown(self): 689 | ${5:pass} 690 | 691 | def test_${6:name}(self): 692 | ${7:${VISUAL:pass}} 693 | endsnippet 694 | 695 | snippet " "triple quoted string (double quotes)" b 696 | """ 697 | ${1:${VISUAL:doc}} 698 | `!p triple_quotes_handle_trailing(snip, '"')` 699 | endsnippet 700 | 701 | snippet ' "triple quoted string (single quotes)" b 702 | ''' 703 | ${1:${VISUAL:doc}} 704 | `!p triple_quotes_handle_trailing(snip, "'")` 705 | endsnippet 706 | 707 | snippet doc "doc block (triple quotes)" 708 | `!p snip.rv = triple_quotes(snip)` 709 | ${1:${VISUAL:doc}} 710 | `!p snip.rv = triple_quotes(snip)` 711 | endsnippet 712 | 713 | snippet pmdoc "pocoo style module doc string" b 714 | # -*- coding: utf-8 -*- 715 | """ 716 | `!p snip.rv = get_dir_and_file_name(snip)` 717 | `!p snip.rv = '~' * len(get_dir_and_file_name(snip))` 718 | 719 | ${1:DESCRIPTION} 720 | 721 | :copyright: (c) `date +%Y` by ${2:YOUR_NAME}. 722 | :license: ${3:LICENSE_NAME}, see LICENSE for more details. 723 | """ 724 | $0 725 | endsnippet 726 | 727 | # vim:ft=snippets: 728 | --------------------------------------------------------------------------------