Skip to content

Commit 3e4468c

Browse files
committed
cleanups and example additions along with doctests
1 parent 09a1554 commit 3e4468c

File tree

10 files changed

+171
-56
lines changed

10 files changed

+171
-56
lines changed

docs/python/classes.md

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,17 @@ sidebar_label: Classes
88

99
* Avoid inbuilt names.
1010
* Classes names should always be `PascalCase`. i.e. `MyClass`
11-
* Use [abstract containers](https://docs.python.org/3/library/collections.abc.html#module-collections.abc) if need to override datatypes.
12-
+ If you must build datatypes based on inbuilt class use PascalCase. i.e. `MyDict(dict):`.
11+
* **Abstract Classes and Mixins**
12+
+ Use [abstract containers](https://docs.python.org/3/library/collections.abc.html#module-collections.abc) if need to override datatypes.
13+
- If you must build datatypes based on inbuilt class use PascalCase. i.e. `MyDict(dict):`.
14+
+ Use [`abc`](https://docs.python.org/3/library/abc.html) if you need pure OOP style abstract classes. Use `NotImplementedError` exceptions with overrides.
15+
+ mixin should be named with `Mixin` suffix such as `class LoginRequiredMixin` which can be used in multiple inheritance.
1316
* Describe the class responsibility in name.
1417
* Custom Exceptions should always be named ending with `Error` i.e. `MyCustomError`
1518

1619
##### Example
1720

18-
```
21+
```python
1922
class HelloWorld:
2023
pass
2124

docs/python/docstrings.md

Lines changed: 91 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ may simply be construed as a comment
3232

3333
To illustrate this try the following in the python console
3434

35-
```python3
35+
```python
3636
class Test:
3737
"""This is a class docstring
3838
"""
@@ -48,28 +48,28 @@ class Test:
4848
```
4949

5050

51-
```python3
51+
```python
5252
> print(Test.__doc___)
5353
This is a class docstring
5454
>
5555
> print(Test.example_method.__doc__)
5656
This is a method docstring
5757
>
58-
> print(Test.example_method_2.__doc__
58+
> print(Test.example_method_2.__doc__)
5959
None
6060
```
6161

6262
As you can see from the examples above, docstrings get
6363
attached to the `__doc__` property of the code itself whereas,
64-
the comments do not
64+
the comments do not.
6565

6666

6767
### Usage of docstrings
6868

6969
From the console, you can use docstrings to an overview of
70-
code as follows
70+
code as follows:
7171

72-
```python3
72+
```python
7373
> help(Test)
7474
Help on class Test in module __main__:
7575

@@ -87,7 +87,9 @@ class Test(builtins.object)
8787
```
8888

8989
If a docstring is provided, you can get more readable
90-
information about python code
90+
information about python code.
91+
92+
** They are also used by your IDE to give you information while developing.**
9193

9294
Furthermore, there are tools that can take this to the
9395
next level by creating a static website of documentation
@@ -122,12 +124,11 @@ template for consistency and also for libraries to be able to
122124
parse your docstring easily.
123125

124126
The official documentation standard for Python is ReStructed Text docstrings ([PEP 287](https://www.python.org/dev/peps/pep-0287/)).
125-
However, Google docstrings have been widely accepted by the community as such we recommend it.
126-
If you're using using Numpy related libraries, it is better
127-
to use Numpy Docstrings
127+
However, Google docstrings have been widely accepted by the community as such we recommend it as we find it more readable and pythonic.
128+
If you're using using Numpy related libraries, you should be using Numpy Docstrings
128129

129-
- [reStructured Text Docstrings](http://docutils.sourceforge.net/rst.html)
130130
- [Google docstrings](https://github.com/google/styleguide/blob/gh-pages/pyguide.md#38-comments-and-docstrings) (**Recommended**)
131+
- [reStructured Text Docstrings](http://docutils.sourceforge.net/rst.html) (Seen in many inbuilt python libraries.)
131132
- [Numpy Docstrings](https://numpydoc.readthedocs.io/en/latest/format.html) (**Recommended for AI projects**)
132133

133134

@@ -193,7 +194,7 @@ to check that your docstrings render correctly
193194

194195
### Google Docstrings (recommended)
195196

196-
```python3
197+
```python
197198

198199
"""Example Google style docstrings.
199200
@@ -496,9 +497,12 @@ class ExampleClass:
496497

497498
### ReStructured Text Doc strings
498499

499-
Here are few examples of docstrings to get you started
500+
You can see this kind of docstring especially in python libraries.
501+
Please use **Google** style as they are more readable.
502+
503+
##### Examples:
500504

501-
```python3
505+
```python
502506
"""The method below prints a given string twice
503507
504508
The print method has been called twice for
@@ -514,12 +518,8 @@ def print_twice(param1):
514518
print(param1)
515519

516520
return len(param1)
517-
```
518521

519-
The following shows type definition on the same line.
520-
521-
```python3
522-
"""The method below prints a given string twice
522+
"""The method below prints a given string twice. This is for type annotation.
523523
524524
The print method has been called twice for
525525
implementing this method
@@ -528,13 +528,84 @@ implementing this method
528528
:return: Length of the input string
529529
:rtype: int
530530
"""
531-
def print_twice(param1):
531+
def print_twice(param1: str) -> int:
532532
print(param1)
533533
print(param1)
534534

535535
return len(param1)
536536
```
537537

538+
## Doctests
539+
:::caution
540+
While this should not be used for all checks and [testing](testing.md) should be followed. They can be used for simple parameter checking. i.e. some default case like module level doctest in example below.
541+
542+
They can be used with [pytest](https://docs.pytest.org/en/latest/doctest.html) as well.
543+
:::
544+
545+
Python provides tests through docstrings which can be leveraged by [doctests](https://docs.python.org/3/library/doctest.html).
546+
547+
Example
548+
```python
549+
"""
550+
This is the "example" module.
551+
552+
The example module supplies one function, factorial(). For example,
553+
554+
>>> factorial(5)
555+
120
556+
"""
557+
558+
def factorial(n):
559+
"""Return the factorial of n, an exact integer >= 0.
560+
561+
>>> [factorial(n) for n in range(6)]
562+
[1, 1, 2, 6, 24, 120]
563+
>>> factorial(30)
564+
265252859812191058636308480000000
565+
>>> factorial(-1)
566+
Traceback (most recent call last):
567+
...
568+
ValueError: n must be >= 0
569+
570+
Factorials of floats are OK, but the float must be an exact integer:
571+
>>> factorial(30.1)
572+
Traceback (most recent call last):
573+
...
574+
ValueError: n must be exact integer
575+
>>> factorial(30.0)
576+
265252859812191058636308480000000
577+
578+
It must also not be ridiculously large:
579+
>>> factorial(1e100)
580+
Traceback (most recent call last):
581+
...
582+
OverflowError: n too large
583+
"""
584+
585+
import math
586+
if not n >= 0:
587+
raise ValueError("n must be >= 0")
588+
if math.floor(n) != n:
589+
raise ValueError("n must be exact integer")
590+
if n+1 == n: # catch a value like 1e300
591+
raise OverflowError("n too large")
592+
result = 1
593+
factor = 2
594+
while factor <= n:
595+
result *= factor
596+
factor += 1
597+
return result
598+
599+
600+
if __name__ == "__main__":
601+
import doctest
602+
doctest.testmod()
603+
```
604+
This can be tested with:
605+
```
606+
$python example.py -v
607+
```
608+
538609
## References
539610

540611
Thanks to the following

docs/python/environment_and_dependency.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ sidebar_label: Environment Isolation and Dependency Management
66

77
#### Information on development environment and dependency:
88

9-
##### Environment Isolation:
9+
### Environment Isolation:
1010

1111
* System installed `python` should never be used for development. Isolate your development.
1212
* Any of the following can be used for python isolation:
@@ -17,7 +17,8 @@ sidebar_label: Environment Isolation and Dependency Management
1717

1818

1919

20-
##### Dependency Management:
20+
### Dependency Management:
2121

2222
* [poetry](https://python-poetry.org/) is recommended as it handles dependency as well as build system.
2323
* You can use `setuptools` and `setup.py` as well for requirements handling through `requires`. They **must** be used for install-able modules.
24+
* `requirements.txt` style should not be avoided.

docs/python/exceptions.md

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,33 @@ sidebar_label: Exception Handling
99
* `Exception` handling is a must and should be mitigated.
1010
* Do not use bare `except` or `except Exception` which catches all the exception.
1111
- Always be specific on exception. E.g. catch only `FileNotFoundError` if you are say moving a file.
12-
* User Defined Exceptions:
12+
* **User Defined Exceptions**:
1313
- Write your custom error only when your error is not described or fulfilled by [internal exceptions](https://docs.python.org/3/library/exceptions.html).
1414
- Create custom `Exception` class primarily suffixing it with `Error` such as `MyCustomError(Exception)` and use it.
1515
- Always use `Exception` as your parent class for user defined exceptions. Donot use `BaseException`.
1616
* Add traceback to your mitigation. i.e. either `logging` or mails. Donot `pass`.
1717
* The `try` block should be specific to desired exception. Donot use huge code chunk in `try`. Use `else` if needed.
18+
```python
19+
try:
20+
value = int(some_str)
21+
except ValueError: # when not using exception object
22+
WHEN some_str IS not valid as value.
23+
except TypeError:
24+
WHEN some_str IS OTHER TYPE such as [], ()
25+
else: #can be avoided if exceptions are handled and returned. This is in context to try block.
26+
DO SOMETHING WITH VALUE
27+
28+
try:
29+
value = int(some_str)
30+
except (ValueError, TypeError) as error:
31+
HANDLE BOTH exception and use exception object
32+
else: # If needed
33+
do something when try succeeds.
34+
finally:
35+
codebase to run anyway
36+
```
37+
* `finally` can be used if you need to run the block whatever the case. `context` can be used in many cases to avoid `finally`.
38+
* `sys.exc_info` and [`traceback`](https://docs.python.org/3/library/traceback.html) can be used for traceback.
39+
* Please read [this](https://cosmicpercolator.com/2016/01/13/exception-leaks-in-python-2-and-3/) on exceptions handling internals and leaks when referencing exceptions.
40+
1841

docs/python/functions.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ sidebar_label: Functions
1414
* `decorators` should be named in function convention.
1515

1616

17-
```
17+
```python
1818
def get_db_connection(username, db_name):
1919
return connection
2020

docs/python/general.md

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -23,34 +23,51 @@ sidebar_label: General Coding Guidelines
2323
- Try to use parent namespace for actions. i.e. `import sys: sys.path` rather that `from sys import path`
2424
- Never use `import *` i.e. `from MODULE import *`
2525
- use namespace whenever possible. Use `as SOMEOTHERNAMESPACE` for collision of namespace
26-
* Use `else: #nobreak` if you are using `else` with loops that has `break`.
26+
* If you are using `else` with loops that has `break`. Just comment `#nobreak` for reference as it is for that usage. See [this](http://python-notes.curiousefficiency.org/en/latest/python_concepts/break_else.html) for some clarity.
27+
```python
28+
for each in each_collection:
29+
if condition:
30+
break
31+
else: #nobreak
32+
ELSE LOGIC
33+
34+
while True:
35+
if condition:
36+
break
37+
else: #nobreak
38+
ELSE LOGIC
39+
```
2740
* Use `pathlib` for path related use case rather than `os.path`
2841
* Use `mypy` and type annotation when possible for type safe code.
29-
* `Docker` can be used for deployment. Use `python` images for [docker](https://hub.docker.com/_/python).
42+
* `Docker` can be used for deployment. Use `python` images for [`docker`](https://hub.docker.com/_/python).
3043
* Use `generators` and `yield` instead of data structures for high streams of data.
31-
* Use `itertools`, `functools` for utilities and `collection` for data structures.
44+
* Use `itertools`, `functools` for utilities and `collections` for data structures.
3245
* Use `dataclasses` if available. Go for `attrs` library if `dataclass` is not present.
33-
* Use `is not` and `is` for `None`, `True` and `False` specific check only. If most cases truthy and falsy can be checked with if `VARNAME:`.
46+
* Use `is not` and `is` for `None`, `True` and `False` specific check only. If most cases truthy and falsy can be checked with `if VARNAME:`.
3447
* Strings:
35-
- Adhere to one quote practice. Double quote is recommended. Python doesnot differentiate between **'** or **"**.
48+
- Adhere to one quote practice. Double quote is recommended. Python doesnot differentiate between **'** or **"**. This may be controlled by `formatter` used as well.
3649
- Should be interpolated with either [fstring](https://www.python.org/dev/peps/pep-0498/) or `.format` methods. Try to avoid `%`.
3750
+ `format_map` should be used for key mapped formatting.
3851
- `+` can be used for direct string concatenation. Use `join` method for concatenation instead of `+=` when iterating.
3952
* Use `context` whenever supported especially for io related closing actions.
4053
- i.e. `with` statement when supported.
4154
- Always remember to close on exit. i.e. if you open the file `close` on `finally` or better use `with` or `contextlib.closing`.
42-
* While `python` is an OOP, you can always choose `functions` and `modules` over `class` if there is only one `object` to be created.
43-
* Use `property` setter when writing OOP and you need readonly attributes.
55+
* **OOP**
56+
- While `python` is an OOP, you can always choose `functions` and `modules` over `class` if there is only one `object` to be created like `Singletons`.
57+
- Use [`abc`](https://docs.python.org/3/library/abc.html) if you need abstraction. Mixins are more famous in python due to multiple inheritance.
58+
- Use `property` setter getter only when you need readonly attributes. `__` variables can be used for some privacy.
59+
- Use `super` for overrides and parent calls.
4460
* Use `pdb` as debugger whenever required.
4561
* Multi-threading can be especially used when we have io bound and network bound multiple operation. Multiprocessing can be used to use multiple cores.
4662
- Recommended module is `concurrent.futures` in most cases. If lower level API is needed there is always `threading` and `multiprocessing` module.
47-
- Be very carefult on threads and locks, so always discuss what you are doing.
63+
- Be very carefult on threads and locks, so always discuss what you are doing as it may not always be optimized.
4864
- Use `asyncio` for IO bound async flow. This is something new and constantly changing in `python`.
4965
* Recommended third party modules:
5066
- For Relational Database:
51-
+ Use `sqlalchemy` [core](https://docs.sqlalchemy.org/en/13/core/) for DB abstraction. This is particularly helpful when doing testing in `sqlite` and some other database for production. Also, for query consistency.
52-
+ Use `sqlalchemy` [ORM](https://docs.sqlalchemy.org/en/13/orm/) or framework supported ORM when using specific framework.
53-
+ Use DBAPI drivers such as `pyodbc`, `sqlite`, `mysqlclient` etc only when you donot want `sqlalchemy` dependency or when you are very performance conscious. While the API will be mostly compatible for this as python has DBAPI specification. Parameters binding and some methods may be incompatible or unavailable.
67+
+ Use `sqlalchemy` [core](https://docs.sqlalchemy.org/en/13/core/) for DB abstraction. This is particularly helpful when doing testing in `sqlite` and some other database for production. Also, for query and parameters consistency.
68+
+ Use `sqlalchemy` [ORM](https://docs.sqlalchemy.org/en/13/orm/) or framework supported **ORM** when using specific framework.
69+
+ Use DBAPI drivers such as `pyodbc`, `sqlite`, `mysqlclient` etc only when you donot want `sqlalchemy` dependency or when you are very performance conscious. While the API will be mostly compatible for this as python has DBAPI specification. Parameters binding and some methods may be incompatible or unavailable. **sqlalchemy core is recommended.**
5470
- `requests` for http request stuff.
55-
- `attrs` for data oriented objects and class.
71+
+ `aiohttp` or `httpx` are also good.
72+
- `attrs` for data oriented objects and classes design.
5673
- `pytest` for tests.

docs/python/logging.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ sidebar_label: Logging Convention
1313
- **WARN**: log user security and other warnings that may require attention or may need to be avoided.
1414
- **ERROR**: errors in programs.
1515
- **CRITICAL**: blocking issues or immediate attention issues.
16-
* **ERROR and CRITICAL** levels should be mitigated and informed.
1716
* `logger` is used for naming single logger object. Use `NAME_logger` name for more than one logger when required.
1817
* It is singleton and single threaded by default for given name of the logger. Can be [non-blocking](https://docs.python.org/3/howto/logging-cookbook.html#dealing-with-handlers-that-block) if required.
19-
* [Logging Cookbook](https://docs.python.org/3/howto/logging-cookbook.html) for reference.
20-
* Always use `exception` method rather than `error` method of `logger` object to log traceback when catching exceptions.
18+
* See [Logging Cookbook](https://docs.python.org/3/howto/logging-cookbook.html) for reference.
19+
* **ERROR and CRITICAL** levels should be mitigated and informed.
20+
- Always use `exception` method rather than `error` method of `logger` object to log traceback when catching exceptions.

docs/python/project_structure.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ title: Project Structure and Templates
44
sidebar_label: Project Structure
55
---
66

7-
### The following folder structure should be used for projects:
7+
#### The following folder structure should be used for projects:
88

99

1010
* :file_folder: Project Root:
@@ -24,13 +24,13 @@ sidebar_label: Project Structure
2424
- :memo: README (can be `md` or `rst`)
2525
- Other configurable from third parties (**OPTIONAL**) such as tox.ini
2626

27-
27+
:::note
2828
+ **There can be cases where MVC folder structure as well as framework related folder structure can be used.**
29-
- The framework recommended structure shoudl be followed in such case.
30-
+ The OOP style cases of class as filename structue is not always necessary but can be used if needed.
31-
29+
- The framework recommended structure should be followed in such case.
30+
+ The OOP style cases of class as filename structue is not always necessary or recommended but can be used if needed.
31+
:::
3232

3333

34-
##### Template Generation:
34+
### Project Template Generation Tool
3535
* Look into [cookiecutter](https://cookiecutter.readthedocs.io/en/1.7.2/) tool for template generation.
3636
- [List of templates for cookiecutter](http://cookiecutter-templates.sebastianruml.name/)

docs/python/testing.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ sidebar_label: Testing
1313
* `tox` and `nox` are vey good tools especially for CI and multiple version tests.
1414
* `hypothesis` and `mock` can be used for faking data and property testing.
1515
* Testing should be broken to `unit` as well as `functional`.
16-
* Use `coverage` to alert yourself of test coverage.
16+
* Use `coverage` to alert yourself of test coverage. Keep a target of **80 % - 90 %** coverage if **100%** is not achieved.
1717
* Only test the changes you made or functionality you added when testing a codebase of well known frameworks.
1818
* `selenium` as well as `webtest` can be used for web based API testing.
1919
* `jsonschema` and `genson` like tool can be used for JSON validity.

0 commit comments

Comments
 (0)