You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@libcloud.apache.org by to...@apache.org on 2019/12/05 19:36:46 UTC

[libcloud] 01/06: Add docs on using type annotations.

This is an automated email from the ASF dual-hosted git repository.

tomaz pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/libcloud.git

commit c88c9c699b00b57d2ac1c0395aba9c1cfa74b465
Author: Tomaz Muraus <to...@tomaz.me>
AuthorDate: Thu Dec 5 20:19:30 2019 +0100

    Add docs on using type annotations.
---
 docs/developer_information.rst           | 28 +++++++++++++++++++
 docs/examples/compute/example_compute.py | 48 ++++++++++++++++++++++++++++++++
 2 files changed, 76 insertions(+)

diff --git a/docs/developer_information.rst b/docs/developer_information.rst
index a91ad84..57da5ab 100644
--- a/docs/developer_information.rst
+++ b/docs/developer_information.rst
@@ -1,6 +1,34 @@
 Developer Information
 =====================
 
+Type Annotations
+----------------
+
+Python type annotations / hints for the base Libcloud compute API have been
+added in v2.7.0.
+
+The goal behind type annotations is to make developer lives easier by
+introducing optional static typing for Python programs.
+
+This allows you to catch bugs and issues which are related to variable types
+earlier and faster (aka when you run ``mypy`` locally either manually or
+integrated in your editor / IDE and also as part of you CI/CD build
+pipeline).
+
+An example of how to use type annotations correctly is shown below.
+
+.. literalinclude:: /examples/compute/example_compute.py
+
+If you are using driver methods which are not part of the Libcloud standard
+API, you need to use ``cast()`` method as shown below to cast the driver class
+to the correct type. If you don't do that, ``mypy`` will only be aware of the
+methods which are part of the Libcloud base compute API (aka
+``BaseNodeDriver`` class).
+
+This is needed because of how Libcloud utilizes meta programming for the
+``get_driver()`` and related methods (there is no other way without writing
+a mypy plugin to achieve that).
+
 .. _mailing-lists:
 
 Mailing Lists
diff --git a/docs/examples/compute/example_compute.py b/docs/examples/compute/example_compute.py
new file mode 100644
index 0000000..92b2202
--- /dev/null
+++ b/docs/examples/compute/example_compute.py
@@ -0,0 +1,48 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You 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
+#
+#     http://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.
+
+from libcloud.compute.types import Provider
+from libcloud.compute.providers import get_driver
+
+from libcloud.compute.drivers.ec2 import EC2NodeDriver
+from libcloud.compute.drivers.rackspace import RackspaceNodeDriver
+
+from typing import Type, cast
+
+ec2_cls = get_driver(Provider.EC2)
+rackspace_cls = get_driver(Provider.RACKSPACE)
+
+# NOTE: If you are using driver methods which are not part of the standard API,
+# you need to explicitly cast the driver class reference to the correct class
+# for type checking to work correctly
+EC2 = cast(Type[EC2NodeDriver], ec2_cls)
+Rackspace = cast(Type[RackspaceNodeDriver], rackspace_cls)
+
+drivers = [EC2('access key id', 'secret key', region='us-east-1'),
+           Rackspace('username', 'api key', region='iad')]
+
+nodes = []
+for driver in drivers:
+    nodes.extend(driver.list_nodes())
+
+print(nodes)
+# [ <Node: provider=Amazon, status=RUNNING, name=bob, ip=1.2.3.4.5>,
+# <Node: provider=Rackspace, status=REBOOT, name=korine, ip=6.7.8.9.10>, ... ]
+
+# grab the node named "test"
+node = [n for n in nodes if n.name == 'test'][0]
+
+# reboot "test"
+node.reboot()