Skip to content

Commit

Permalink
docs: add code samples for Jupyter/IPython magics (#1013)
Browse files Browse the repository at this point in the history
Follow-up to GoogleCloudPlatform/python-docs-samples#6889, which removed a BigQuery magics sample for using query parameters.

Note: jupyter_tutorial_test.py is a copy of what is in the `samples/snippets`
folder. Once the docs have been updated to point to this new version, we can
remove that copy and remove the Jupyter/IPython depedencencies from
`samples/snippets/requirements.txt`.

Thank you for opening a Pull Request! Before submitting your PR, there are a few things you can do to make sure it goes smoothly:
- [ ] Make sure to open an issue as a [bug/issue](https://github.com/googleapis/python-bigquery/issues/new/choose) before writing your code!  That way we can discuss the change, evaluate designs, and agree on the general idea
- [ ] Ensure the tests and linter pass
- [ ] Code coverage does not decrease (if any source code was changed)
- [ ] Appropriate docs were updated (if necessary)
  • Loading branch information
tswast committed Oct 29, 2021
1 parent d64f5b6 commit 61141ee
Show file tree
Hide file tree
Showing 13 changed files with 503 additions and 67 deletions.
29 changes: 29 additions & 0 deletions docs/magics.rst
@@ -1,5 +1,34 @@
IPython Magics for BigQuery
===========================

To use these magics, you must first register them. Run the ``%load_ext`` magic
in a Jupyter notebook cell.

.. code::
%load_ext google.cloud.bigquery
This makes the ``%%bigquery`` magic available.

Code Samples
------------

Running a query:

.. literalinclude:: ./samples/magics/query.py
:dedent: 4
:start-after: [START bigquery_jupyter_query]
:end-before: [END bigquery_jupyter_query]

Running a parameterized query:

.. literalinclude:: ./samples/magics/query_params_scalars.py
:dedent: 4
:start-after: [START bigquery_jupyter_query_params_scalars]
:end-before: [END bigquery_jupyter_query_params_scalars]

API Reference
-------------

.. automodule:: google.cloud.bigquery.magics.magics
:members:
66 changes: 0 additions & 66 deletions google/cloud/bigquery/magics/magics.py
Expand Up @@ -14,15 +14,6 @@

"""IPython Magics
To use these magics, you must first register them. Run the ``%load_ext`` magic
in a Jupyter notebook cell.
.. code::
%load_ext google.cloud.bigquery
This makes the ``%%bigquery`` magic available.
.. function:: %%bigquery
IPython cell magic to run a query and display the result as a DataFrame
Expand Down Expand Up @@ -85,63 +76,6 @@
.. note::
All queries run using this magic will run using the context
:attr:`~google.cloud.bigquery.magics.Context.credentials`.
Examples:
The following examples can be run in an IPython notebook after loading
the bigquery IPython extension (see ``In[1]``) and setting up
Application Default Credentials.
.. code-block:: none
In [1]: %load_ext google.cloud.bigquery
In [2]: %%bigquery
...: SELECT name, SUM(number) as count
...: FROM `bigquery-public-data.usa_names.usa_1910_current`
...: GROUP BY name
...: ORDER BY count DESC
...: LIMIT 3
Out[2]: name count
...: -------------------
...: 0 James 4987296
...: 1 John 4866302
...: 2 Robert 4738204
In [3]: %%bigquery df --project my-alternate-project --verbose
...: SELECT name, SUM(number) as count
...: FROM `bigquery-public-data.usa_names.usa_1910_current`
...: WHERE gender = 'F'
...: GROUP BY name
...: ORDER BY count DESC
...: LIMIT 3
Executing query with job ID: bf633912-af2c-4780-b568-5d868058632b
Query executing: 2.61s
Query complete after 2.92s
In [4]: df
Out[4]: name count
...: ----------------------
...: 0 Mary 3736239
...: 1 Patricia 1568495
...: 2 Elizabeth 1519946
In [5]: %%bigquery --params {"num": 17}
...: SELECT @num AS num
Out[5]: num
...: -------
...: 0 17
In [6]: params = {"num": 17}
In [7]: %%bigquery --params $params
...: SELECT @num AS num
Out[7]: num
...: -------
...: 0 17
"""

from __future__ import print_function
Expand Down
3 changes: 2 additions & 1 deletion noxfile.py
Expand Up @@ -186,8 +186,9 @@ def snippets(session):
session.run(
"py.test",
"samples",
"--ignore=samples/snippets",
"--ignore=samples/magics",
"--ignore=samples/geography",
"--ignore=samples/snippets",
*session.posargs,
)

Expand Down
13 changes: 13 additions & 0 deletions samples/magics/__init__.py
@@ -0,0 +1,13 @@
# Copyright 2021 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
21 changes: 21 additions & 0 deletions samples/magics/_helpers.py
@@ -0,0 +1,21 @@
# Copyright 2021 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.


def strip_region_tags(sample_text):
"""Remove blank lines and region tags from sample text"""
magic_lines = [
line for line in sample_text.split("\n") if len(line) > 0 and "# [" not in line
]
return "\n".join(magic_lines)
36 changes: 36 additions & 0 deletions samples/magics/conftest.py
@@ -0,0 +1,36 @@
# Copyright 2021 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import pytest

interactiveshell = pytest.importorskip("IPython.terminal.interactiveshell")
tools = pytest.importorskip("IPython.testing.tools")


@pytest.fixture(scope="session")
def ipython():
config = tools.default_config()
config.TerminalInteractiveShell.simple_prompt = True
shell = interactiveshell.TerminalInteractiveShell.instance(config=config)
return shell


@pytest.fixture(autouse=True)
def ipython_interactive(ipython):
"""Activate IPython's builtin hooks
for the duration of the test scope.
"""
with ipython.builtin_trap:
yield ipython

0 comments on commit 61141ee

Please sign in to comment.