Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Python Styleguide #241

Merged
merged 4 commits into from
Sep 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions doc/_static/idioms/adapter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# With Adapter
for first, item in loop_first([]):
if first:
edge_case(item)
continue
default(item)

# Naive Approach
is_first = True
for items in []:
if is_first:
edge_case(item)
is_first = False
continue
default(item)
11 changes: 11 additions & 0 deletions doc/_static/idioms/concat.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Good
names = ["Peter", "Albert", "Cleo", "Ember"]
output = ", ".join(names)

# Bad
names = ["Peter", "Albert", "Cleo", "Ember"]
output = ""
for name in names:
output += name
if not is_last_element(name):
output += ", "
42 changes: 42 additions & 0 deletions doc/_static/idioms/context_decorator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# With Decorator
import logging
from functools import wraps


def log_execution(f):
@wraps(f)
def wrapper(*args, **kwargs):
logging.debug(f"Entering: {f.__name__}")
result = f(*args, **kwargs)
logging.debug(f"Leaving: {f.__name__}")
return result

return wrapper


@log_execution
def some_function():
return "Some Result"


@log_execution
def other_function():
return "Other Result"


# Naive Approach
import logging


def some_function():
logging.debug("Entering: some_function")
result = "Some Result"
logging.debug("Leaving: some_function")
return result


def other_function():
logging.debug("Entering: other_function")
result = "Some Result"
logging.debug("Leaving: other_function")
return result
Empty file.
40 changes: 40 additions & 0 deletions doc/_static/idioms/context_manager.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# With Context Manager
import os
from contextlib import contextmanager


@contextmanager
def chdir(path):
old_dir = os.getcwd()
os.chdir(path)
yield path
os.chdir(old_dir)


def initialize(directory):
with chdir(directory) as _working_dir:
with open('some-file.txt', 'w') as f:
f.write("Some content")


# With Python 3.11
from contextlib import chdir


def initialize(directory):
with chdir(directory) as _working_dir:
with open('some-file.txt', 'w') as f:
f.write("Some content")


# Naive Approach
import os


def initialize(directory):
old_dir = os.getcwd()
os.chdir(directory)
os.chdir(old_dir)
with open('some-file.txt', 'w') as f:
f.write("Some content")
os.chdir(old_dir)
15 changes: 15 additions & 0 deletions doc/_static/idioms/count.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Good
from collections import Counter

colors = ["green", "blue", "red", "green", "red", "red"]

counts = Counter(colors)

# Bad
from collections import defaultdict

colors = ["green", "blue", "red", "green", "red", "red"]

d = defaultdict(int)
for color in colors:
d[color] += 1
11 changes: 11 additions & 0 deletions doc/_static/idioms/enumerate.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Good
customers = ["Marry", "Thor", "Peter", "Batman"]
for index, customer in enumerate(customers):
print(f"Customer: {customer}, Queue position: {index}")

# Bad
index = 0
customers = ["Marry", "Thor", "Peter", "Batman"]
for customer in customers:
print(f"Customer: {customer}, Queue position: {index}")
index += 1
21 changes: 21 additions & 0 deletions doc/_static/idioms/filters.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# With Filter
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9]
odd = filter(lambda n: n % 2, numbers)
even = (number for number in numbers if not number % 2)

print(f"Sum of odd values: {sum(odd)}")
print(f"Sum of even values: {sum(even)}")

# Naive Approach
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9]
odd = 0
even = 0

for number in numbers:
if number % 2:
odd += number
else:
even += number

print(f"Sum of odd values: {odd}")
print(f"Sum of even values: {even}")
26 changes: 26 additions & 0 deletions doc/_static/idioms/format.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Good
template = """
{heading} - from: {date}
---------------------------------
{users}
"""
output = template.format(
heading="User Overview",
date=datetime.now().strftime("%Y-%m-%d"),
users="\n".join(
(
f"Firstname: {user.first_name}, Lastname: {user.last_name}, Age: {user.age}"
for user in users
)
),
)

# Bad
heading = "User Overview"
date = datetime.now().strftime("%Y-%m-%d")
output = f"{heading} - from: {date}" + "\n"
output += "---------------------------------" + "\n"
for user in users:
output += (
f"Firstname: {user.first_name}, Lastname: {user.last_name}, Age: {user.age}\n"
)
7 changes: 7 additions & 0 deletions doc/_static/idioms/fstring.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Good
output = f"Firstname: {user.first_name}, Lastname: {user.last_name}, Age: {user.age}"

# Bad
output = "Firstname: {}, Lastname: {}, Age: {}".format(
user.first_name, user.last_name, user.age
)
18 changes: 18 additions & 0 deletions doc/_static/idioms/layering.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Good
from collections import ChainMap

cli_args = {"user": "FooBar", "cmd": "ls -all"}
env_args = {"user": "Johndoe"}
cfg_args = {"user": "default", "cwd": "/home/default", "cmd": "ls"}

config = ChainMap(cli_args, env_args, cfg_args)

# Bad
cli_args = {"user": "FooBar", "cmd": "ls -all"}
env_args = {"user": "Johndoe"}
cfg_args = {"user": "default", "cwd": "/home/default", "cmd": "ls"}

config = {}
config.update(cfg_args)
config.update(env_args)
config.update(cli_args)
9 changes: 9 additions & 0 deletions doc/_static/idioms/loop_collection.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Good
colors = ["red", "green", "blue", "yellow"]
for color in colors:
print(color)

# Bad
colors = ["red", "green", "blue", "yellow"]
for i in range(len(colors)):
print(colors[i])
7 changes: 7 additions & 0 deletions doc/_static/idioms/loop_numbers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Good
for i in range(6):
print(i**2)

# Bad
for i in [0, 1, 2, 3, 4, 5]:
print(i**2)
14 changes: 14 additions & 0 deletions doc/_static/idioms/loop_two_collections.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Good
names = ["raymond", "rachel", "matthew"]
colors = ["red", "green", "blue", "yellow"]

for name, color in zip(names, colors):
print(f"{name} --> {color}")

# Bad
names = ["raymond", "rachel", "matthew"]
colors = ["red", "green", "blue", "yellow"]

n = min(len(names), len(colors))
for i in range(n):
print(f"{names[i]} --> {colors[i]}")
4 changes: 4 additions & 0 deletions doc/_static/idioms/named_parameters.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Good
twitter_search("@obama", retweets=False, numtweets=20, popular=True)
# Bad
twitter_search("@obama", False, 20, True)
9 changes: 9 additions & 0 deletions doc/_static/idioms/pairs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Good
colors = ["red", "green", "blue"]
d = dict(enumerate(colors))

# Bad
colors = ["red", "green", "blue"]
d = {}
for i, color in enumerate(colors):
d[i] = color
9 changes: 9 additions & 0 deletions doc/_static/idioms/reverse.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Good
customers = ["Marry", "Brain", "Peter", "Batman"]
for customer in reversed(customers):
print(customer)

# Bad
customers = ["Marry", "Brain", "Peter", "Batman"]
for index in range(len(customers) - 1, -1, -1):
print(customers[index])
12 changes: 12 additions & 0 deletions doc/_static/idioms/sentinel.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Good
blocks = []
for block in iter(partial(f.read, 32), ""):
blocks.append(block)

# Bad
blocks = []
while True:
block = f.read(32)
if block == "":
break
blocks.append(block)
28 changes: 28 additions & 0 deletions doc/_static/idioms/short_circuit.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# With Generator Short Circuit
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9]


def find_number(numbers):
numbers = (n for n in numbers if (n % 3) == 0)
try:
number = next(numbers)
except StopIteration:
number = None
return number


number = find_number(numbers)

# Naive Approach
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9]


def find_number(numbers):
for n in numbers:
# concerns are not seperated
if (n % 3) == 0:
return n
return None


number = find_number(numbers)
11 changes: 11 additions & 0 deletions doc/_static/idioms/unpacking.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Good
person = "John", "Doe", 42, "[email protected]"

firstname, lastname, age, email = person
# Bad
person = "John", "Doe", 42, "[email protected]"

firstname = person[0]
lastname = person[1]
age = person[2]
email = person[3]
2 changes: 2 additions & 0 deletions doc/changes/unreleased.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,6 @@
* Updated actions/checkout to v4

## 📚 Documentation
* Add Python Styleguide
* Add Issue Guide
* Updated User Documentation
2 changes: 2 additions & 0 deletions doc/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@
"sphinx_copybutton",
"myst_parser",
"sphinx_design",
"sphinx_inline_tabs",
"sphinx_copybutton",
]

intersphinx_mapping = {"python": ("https://docs.python.org/3", None)}
Expand Down
16 changes: 15 additions & 1 deletion doc/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,18 @@ Documentation of the Exasol-Toolbox

Instructions and best practices to help developers contribute to the project and set up their development environment.

.. grid-item-card:: :octicon:`paintbrush` Python Styleguide
:link: styleguide
:link-type: ref

Python Style Guide of the Exasol Integration Team

.. grid-item-card:: :octicon:`list-unordered` Issue Tracking Guide
:link: issue_tracking
:link-type: ref

Guide to Issues and Issue Tracking

.. grid-item-card:: :octicon:`terminal` Tools
:link: tools
:link-type: ref
Expand Down Expand Up @@ -51,11 +63,13 @@ Documentation of the Exasol-Toolbox


.. toctree::
:maxdepth: 1
:maxdepth: 4
:hidden:

user_guide/user_guide
developer_guide/developer_guide
styleguide/index
issues
tools
github_actions/github_actions
api
Expand Down
Loading
Loading