Skip to content

Commit

Permalink
Enforce code-block directives in doc (#9443)
Browse files Browse the repository at this point in the history
(cherry picked from commit 60d19dc)
  • Loading branch information
mik-laj authored and kaxil committed Jul 1, 2020
1 parent 4f08d4d commit 45a583f
Show file tree
Hide file tree
Showing 17 changed files with 222 additions and 142 deletions.
38 changes: 19 additions & 19 deletions docs/best-practices.rst
Original file line number Diff line number Diff line change
Expand Up @@ -89,13 +89,13 @@ It can result in a lot of open connections.

The best way of using variables is via a Jinja template which will delay reading the value until the task execution. The template synaxt to do this is:

.. code::
.. code-block::
{{ var.value.<variable_name> }}
or if you need to deserialize a json object from the variable :

.. code::
.. code-block::
{{ var.json.<variable_name> }}
Expand All @@ -117,7 +117,7 @@ DAG Loader Test
This test should ensure that your DAG does not contain a piece of code that raises error while loading.
No additional code needs to be written by the user to run this test.

.. code::
.. code-block::
python your-dag-file.py
Expand All @@ -132,7 +132,7 @@ Unit tests ensure that there is no incorrect code in your DAG. You can write a u

**Unit test for loading a DAG:**

.. code::
.. code-block::
from airflow.models import DagBag
import unittest
Expand All @@ -149,9 +149,9 @@ Unit tests ensure that there is no incorrect code in your DAG. You can write a u
self.assertEqual(len(dag.tasks), 1)
**Unit test a DAG structure:**
This is an example test want to verify the structure of a code-generated DAG against a dict object
This is an example test want to verify the structure of a code-generated DAG against a dict object

.. code::
.. code-block::
import unittest
class testClass(unittest.TestCase):
Expand All @@ -163,16 +163,16 @@ This is an example test want to verify the structure of a code-generated DAG aga
self.assertEqual(task.downstream_task_ids, set(downstream_list),
msg="unexpected downstream link in {}".format(task_id))
def test_dag(self):
self.assertDagDictEqual({
"DummyInstruction_0": ["DummyInstruction_1"],
"DummyInstruction_1": ["DummyInstruction_2"],
"DummyInstruction_2": ["DummyInstruction_3"],
"DummyInstruction_3": []
},dag)
self.assertDagDictEqual({
"DummyInstruction_0": ["DummyInstruction_1"],
"DummyInstruction_1": ["DummyInstruction_2"],
"DummyInstruction_2": ["DummyInstruction_3"],
"DummyInstruction_3": []
},dag)
**Unit test for custom operator:**

.. code::
.. code-block::
import unittest
from airflow.utils.state import State
Expand Down Expand Up @@ -205,7 +205,7 @@ make sure that the partition is created in S3 and perform some simple checks to

Similarly, if you have a task that starts a microservice in Kubernetes or Mesos, you should check if the service has started or not using :class:`airflow.sensors.http_sensor.HttpSensor`.

.. code::
.. code-block::
task = PushToS3(...)
check = S3KeySensor(
Expand All @@ -227,7 +227,7 @@ Do not hard code values inside the DAG and then change them manually according t

You can use environment variables to parameterize the DAG.

.. code::
.. code-block::
import os
Expand All @@ -252,7 +252,7 @@ If you want to run Airflow in production, make sure you :doc:`configure the back

You can change the backend using the following config

.. code:: ini
.. code-block:: ini
[core]
sql_alchemy_conn = my_conn_string
Expand All @@ -261,7 +261,7 @@ Once you have changed the backend, airflow needs to create all the tables requir
Create an empty DB and give airflow's user the permission to ``CREATE/ALTER`` it.
Once that is done, you can run -

.. code::
.. code-block::
airflow upgradedb
Expand Down Expand Up @@ -305,14 +305,14 @@ Airflow comes bundles with a default ``airflow.cfg`` configuration file.
You should use environment variables for configurations that change across deployments
e.g. metadata DB, password. You can do it using the format ``$AIRFLOW__{SECTION}__{KEY}``

.. code::
.. code-block::
AIRFLOW__CORE__SQL_ALCHEMY_CONN=my_conn_id
AIRFLOW__WEBSERVER__BASE_URL=http://host:port
Some configurations such as Airflow Backend connection URI can be derived from bash commands as well:

.. code::
.. code-block::
sql_alchemy_conn_cmd = bash_command_to_run
Expand Down
25 changes: 25 additions & 0 deletions docs/build
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,16 @@ def find_modules(deprecated_only: bool = False) -> Set[str]:
return modules_names


def assert_file_not_contains(file_path: str, pattern: str, message: str) -> None:
with open(file_path, "rb", 0) as doc_file:
pattern_compiled = re.compile(pattern)

for num, line in enumerate(doc_file, 1):
line_decode = line.decode()
if re.search(pattern_compiled, line_decode):
build_errors.append(DocBuildError(file_path=file_path, line_no=num, message=message))


def check_exampleinclude_for_example_dags():
all_docs_files = glob("**/*rst", recursive=True)

Expand All @@ -158,6 +168,20 @@ def check_exampleinclude_for_example_dags():
)


def check_enforce_code_block():
all_docs_files = glob("**/*rst", recursive=True)

for doc_file in all_docs_files:
assert_file_not_contains(
file_path=doc_file,
pattern=r"^.. code::",
message=(
"We recommend using the code-block directive instead of the code directive. "
"The code-block directive is more feature-full."
)
)


def prepare_code_snippet(file_path: str, line_no: int, context_lines_count: int=5) -> str:
def guess_lexer_for_filename(filename):
from pygments.util import ClassNotFound
Expand Down Expand Up @@ -256,6 +280,7 @@ print("Current working directory: ", os.getcwd())
prepare_directories()
clean_files()

check_enforce_code_block()
check_exampleinclude_for_example_dags()

if build_errors:
Expand Down
Loading

0 comments on commit 45a583f

Please sign in to comment.