!Bang are shortcuts that let you target searches on specific sites. And if DuckDuckGo is you browser default search engine you can use it directly from your address bar.
Since Python there is support for annotations of variable types, class fields, arguments, and return values of functions. However it breaks backwards compatibility. If you want to keep it, write types in docstrings.
Basics
Variable annotations are written with a colon after the identifier. This can be followed by value initialization.
1 2
price: int = 5 title: "str"
Function parameters are annotated in the same way as variables, and the return value is specified after the arrow -> and before the trailing colon.
For class fields, annotations must be specified explicitly when the class is defined. However, analyzers can automatically infer them based on the __init__ method, but in this case, they will not be available at runtime:
b: Book = Book(title="Fahrenheit 451", author="Bradbury")
Built-in types (sub-modules)
Optional
1 2 3 4 5 6 7
amount: int amount: None # Gives "Incompatible types" error
price: Optional[int] price: None # It will work!
Any
1 2 3 4 5 6 7 8 9 10 11 12 13
# do not restrict possible types some_item: Any = 1 print(some_item) print(some_item.startswith("hello")) print(some_item // 0)
# object may have some issues, avoid it some_object: object print(some_object) print(some_object.startswith("hello")) # ERROR: "object" has no attribute "startswith" print(some_object // 0) # ERROR: Unsupported operand types for // ("object" and "int")
Union
1 2 3 4 5 6 7 8 9 10 11
# allow only some types defhundreds(x: Union[int, float]) -> int: return (int(x) // 100) % 100
hundreds(100.0) hundreds(100) hundreds("100") # ERROR: Argument 1 to "hundreds" has incompatible type "str"; # expected "Union[int, float]"
# Also `Optional[T]` is equivalent toUnion[T, None]
price_container: Tuple[int] = (1,) price_container: ("hello") # ERROR: Incompatible types in assignment (expression has type "str", # variable has type "Tuple[int]")
price_container = (1, 2) # ERROR: Incompatible types in assignment (expression has type "Tuple[int, int]", # variable has type "Tuple[int]")
price_with_title: Tuple[int, str] = (1, "hello") # Everything is good!
# you can use ellipsis to define an "unknown number of elements" prices: Tuple[int, ...] = (1, 2) prices: (1,) prices: (1, "str") # ERROR: Incompatible types in assignment (expression has type # "Tuple[int, str]", variable has type "Tuple[int]")
# no type specification equals to Tuple[Any, ...] something: Tuple = (1, 2, "hello") # Everything is good!
Dictionaries
1 2 3 4 5 6 7 8 9
# key and type are specified separate book_authors: Dict[str, str] = {"Fahrenheit 451": "Bradbury"} book_authors["1984"] = 0 # ERROR: Incompatible types in assignment # (expression has type "int", target has type "str")
book_authors[1984] = "Orwell" # ERROR: Invalid index type "int" for "Dict[str, str]"; # expected type "str"
There is also typing.DefaultDict and typing.OrderedDict
Function execution results
Function returns nothing:
1 2 3 4 5 6 7 8 9 10
defnothing(a: int) -> None: if a == 1: return elif a == 2: return elif a == 3: # No return value expected return"" else: pass
Function never returns control (e.g. sys.exit)
1 2 3
defforever() -> NoReturn: whileTrue: pass
Generator function (its body contains an operator yield)
1 2 3 4 5
defgenerate_two() -> Iterable[int]: yield1 yield"2" # ERROR: Incompatible types in "yield" # (actual type "str", expected type "int")
"""Module for Google style docstrings example. This module demonstrates documentation as specified by the `Google Python Style Guide`_. Docstrings may extend over multiple lines. Sections are created with a section header and a colon followed by a block of indented text. Example: Examples can be given using either the ``Example`` or ``Examples`` sections. Sections support any reStructuredText formatting, including literal blocks:: $ python example_google.py Section breaks are created by resuming unindented text. Section breaks are also implicitly created anytime a new section starts. Attributes: module_level_variable1 (int): Module level variables may be documented in either the ``Attributes`` section of the module docstring, or in an inline docstring immediately following the variable. Either form is acceptable, but the two should not be mixed. Choose one convention to document module level variables and be consistent with it. Todo: * For module TODOs """ module_level_variable1 = 12345 module_level_variable2 = 98765
deffunction_with_types_in_docstring(param1, param2): """Example function with types documented in the docstring. `PEP 484`_ type annotations are supported. If attribute, parameter, and return types are annotated according to `PEP 484`_, they do not need to be included in the docstring: Args: param1 (int): The first parameter. param2 (str): The second parameter. Returns: bool: The return value. True for success, False otherwise. .. _PEP 484: https://www.python.org/dev/peps/pep-0484/ """ return param1 == param2
# no template pandoc README.md -o output-readme.docx # with template, you must generate one first pandoc -o custom-reference.docx --print-default-data-file reference.docx pandoc -t docx README.md --reference-doc=template.docx -o output-template.docx
You will need a lua script (pagebreak.lua) into the pandoc folder, so you can use <!-- \newpage --> in your document to split into pages without further issues.
--- Return a block element causing a page break in the given format. localfunctionnewpage(format) ifformat == 'docx'then local pagebreak = '<w:p><w:r><w:br w:type="page"/></w:r></w:p>' return pandoc.RawBlock('openxml', pagebreak) elseifformat:match'html.*'then return pandoc.RawBlock('html', '<div style=""></div>') elseifformat:match'tex$'then return pandoc.RawBlock('tex', '\\newpage{}') elseifformat:match'epub'then local pagebreak = '<p style="page-break-after: always;"> </p>' return pandoc.RawBlock('html', pagebreak) else -- fall back to insert a form feed character return pandoc.Para{pandoc.Str '\f'} end end
-- Filter function called on each RawBlock element. functionRawBlock(el) -- check that the block is TeX or LaTeX and contains only \newpage or -- \pagebreak. if el.text:match'\\newpage'then -- use format-specific pagebreak marker. FORMAT is set by pandoc to -- the targeted output format. return newpage(FORMAT) end -- otherwise, leave the block unchanged returnnil end
# deletes a key pair and deployment artifacts delete_all_artifacts # resumes any suspended processes in auto-scaling groups resume_all_autoscaling_processes
# deletes the CloudFormation stack specified in the inputs aws cloudformation delete-stack \ --stack-name "$stack_name"
Designing the tests
Test cases
a usage message is expected if incorrect inputs are passed
for a stack with no auto-scaling groups:
key pairs and deployment artifacts are expected to be deleted
aws cloudformation delete-stack should be issued
for a stack with multiple auto-scaling groups:
a resume-processes command should be issued for each auto-scaling group
Issue: it doesn’t try to handle a non-existent S3 bucket and a non-existent CloudFormation stack. So we can:
document this as a known issue
fixing the script to be more defensive (recommended!)
writing tests to test for and demonstrate the known issue
Structure of the tests on shunit2/delete_stack.sh
the variable $script_under_test as mentioned above
a mocks section to replace commands that make calls to AWS
a more general setup/teardown section
some test cases, being the shell functions whose names start with test*
# diff -wu ensures that during failures, a nice readable unified diff # of “expected” compared to “actual” is seen assertEquals "unexpected sequence of commands issued" \ """$(diff -wu expected_log commands_log | colordiff | DiffHighlight.pl)" }
# section 5 - the call to shUnit2 itself . shunit2
Bad inputs
Test cases
1 2 3 4 5 6 7
# check if the input on method call is wrong testBadInputs() { # STDOUT is captured using command substitution $( ... ) actual_stdout=$(. "$script_under_test" too many arguments passed) assertTrue "unexpected response when passing bad inputs" \ "echo $actual_stdout | grep -q ^Usage" }
"aws cloudformation describe-stack-resources \ --stack-name myotherstack \ --query "'StackResources[?ResourceType== \ `AWS::AutoScaling::AutoScalingGroup`].PhysicalResourceId'" \ --output text") ## Manual tests show that this command returns an empty string for this echo"" ;;