Skip to content

Commit e6bc9e4

Browse files
committed
Merge pull request #73 from dbrian56/documentation
Documentation
2 parents c95e9d1 + 55d255c commit e6bc9e4

File tree

3 files changed

+62
-74
lines changed

3 files changed

+62
-74
lines changed

docs/advanced.rst

Lines changed: 51 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -2,68 +2,60 @@
22

33
Advanced Topics
44
===============
5-
This Section serves as a collective for advanced topics that most developers
6-
using this library will never need to know about, but that may be useful for
7-
developers who are destined to maintain this package
5+
This section is a collection of advanced topics for users who intend to contribute
6+
and maintain this library.
87

98
Sessions
109
--------
1110

12-
The way in which sessions are handled in this library are designed to be super
13-
easy to use for developers who use this library, however, have become relatively
14-
complex internally. Due to their ease of use to the front end user these docs are
15-
mainly for developers who would like to contribute to this code base, or who are
16-
just curious as to what is actually going on under the hood.
11+
Sessions in this library are designed for ease of use by front-end users.
12+
However, this section is dedicated to a deeper understanding of Sessions for
13+
advanced users and contributors to this library.
1714

1815
Parent Class
1916
^^^^^^^^^^^^
2017
Both :class:`dyn.tm.session.DynectSession` and :class:`dyn.mm.session.MMSession`
2118
are subclasses of :class:`dyn.core.SessionEngine`. The :class:`dyn.core.SessionEngine`
22-
provides an easy to use internal API for preparing, sending, and processing outbound
23-
API calls. This class was added in v1.0.0 and greatly reduced the amount of logic
24-
and duplicated code that made looking at these sessions so overly complex.
19+
provides a simple internal API for preparing, sending, and processing outbound
20+
API calls. This class was added in v1.0.0 and reduced the amount of logic
21+
and duplicated code that made understanding these Sessions difficult.
2522

2623
Parent Type
2724
^^^^^^^^^^^
28-
Since v0.4.0 sessions had always been implemented as a Singleton type. At this point
29-
you're probably asing "Why?" And that's a bit of a complicated question. One of the main
30-
reasons that these sessions were implemented as a Singleton was to make it easier for
31-
the end user to use this SDK and to make the flow of logic in trying to utilize the
32-
API much smoother. By implementing Sessions as a singleton internally, it allows the
33-
user to not need to hang on to their session objects (unless they want to). It also
34-
means that users don't need to pass their session information around to all of the other
35-
classes in this library in order to make API calls. (ie)::
25+
Since v0.4.0, Sessions have been implemented as a Singleton type. This made it easier
26+
for end users to use the SDK and to utilize the API. By internally implementing Sessions
27+
as a Singleton, it allows the user discard their Session objects, unless they wish to
28+
keep them. It also doesn’t require users to share their Session information with
29+
other classes in this library to make API calls. (EXAMPLE)::
3630

3731
>>> from dyn.tm.session import DynectSession
3832
>>> from dyn.tm.zones import get_all_zones
3933
>>> DynectSession(**my_credentials)
4034
>>> zones = get_all_zones()
4135

4236

43-
as opposed to something along these lines::
37+
as opposed to something like this::
4438

4539
>>> from dyn.tm.session import DynectSession
4640
>>> from dyn.tm.zones import get_all_zones
4741
>>> my_session = DynectSession(**my_credentials)
4842
>>> zones = get_all_zones(my_session)
4943

50-
Or, in my opinion, even worse::
44+
Or, even worse::
5145

5246
>>> from dyn.tm.session import DynectSession
5347
>>> my_session = DynectSession(**my_credentials)
5448
>>> zones = my_session.get_all_zones(my_session)
5549

56-
In these basic examples it may not seem like this is a terribly huge deal, but when
57-
you're dealing with creating multiple types of records, or adding/editing a Traffic
58-
Director service or other complex service, not needing to pass your session around
59-
to the correct places, or use it as a point of entry to other functionality is a huge
60-
relief.
50+
In these examples, the changes may not seem significant but gain more relevance when
51+
creating multiple types of records, adding or editing Traffic Director and other complex
52+
services. Not needing to share your Session with other classes, or use it as a point
53+
of entry to other functionality, makes using this SDK much simpler.
6154

6255
What We Used to Do
6356
^^^^^^^^^^^^^^^^^^
64-
Now that we've gone over the Singleton implementation from a front end POV, let's
65-
talk about it from a backend POV. Effectively what we used to do in each of the Session
66-
types was this::
57+
From a backend perspective, the following is an example of how Session types were
58+
handled before v0.4.0::
6759

6860
def session():
6961
"""Accessor for the current Singleton DynectSession"""
@@ -89,19 +81,17 @@ types was this::
8981
globals()['SESSION'] = super(DynectSession, cls).__new__(cls, *args)
9082
return globals()['SESSION']
9183

92-
It was a dirty hack that worked for a while, but, it had several fatal flaws.
93-
1. Once we added Message Management support we needed to duplicate this code to rename the 'SESSION' key to 'MM_SESSION', which is less than ideal due to code duplication
94-
2. This allowed you to only have one active session, even in shared memory space (ie threads)
95-
3. Due to the not-so-global scope of globals, this session was really only "global" in the scope of the dyn.tm module. It could still be accessed externally, but it just made me feel dirty knowing that that was what was happening.
84+
While this worked for a short while, it had its flaws:
85+
1. Once Message Management support was added, the code needed to be duplicated to rename the SESSION key to MM_SESSION’. This was inefficient.
86+
2. This allowed you to only have one active Session, even in shared memory space, i.e. threads.
87+
3. Sessions were only truly “global in the scope of the dyn.tm module. It could still be accessed externally, but it was less than ideal.
9688

9789
What We Do Now
9890
^^^^^^^^^^^^^^
99-
So, as of v1.0.0 this is not how the Session types are implemented anymore. Yes, they
100-
are still Singletons, however, they're implemented completely differently.
91+
As of v1.0.0, Session types remain Singletons but are implemented differently.
10192

102-
Now, on top of these Sessions being implemented as :class:`dyn.core.SessionEngine`
103-
objects, they are also :class:`dyn.core.Singleton` *type* objects. What do these
104-
look like you ask?::
93+
Sessions are now implemented as :class:`dyn.core.SessionEngine` objects
94+
and :class:`dyn.core.Singleton` *type* objects. EXAMPLE::
10595

10696
class Singleton(type):
10797
"""A :class:`Singleton` type for implementing a true Singleton design
@@ -119,44 +109,40 @@ look like you ask?::
119109
}
120110
return cls._instances[key][cur_thread]
121111

122-
So, the Singleton type is applied as a *__metaclass__* in each of the two Session
123-
types. This allows for a much cleaner implementation of Singletons where every time
124-
one is accessed it will globally (actually globally this time) have knowledge of
125-
other instances, since those instances are tied to the classes themselves instead
126-
of held in the *globals* of the session modules. In addition this allows users
127-
to have multiple active sessions across multiple threads, which was previously
128-
impossible in the prior implementation.
112+
The Singleton type is applied as a *__metaclass__* in each of the two Session
113+
types. This allows for a much cleaner implementation of Singletons. Every time
114+
one is accessed, it will globally have knowledge of other instances, as those
115+
instances are tied to the classes themselves instead of held in the *globals*
116+
of the session modules. In addition, this allows users to have multiple active
117+
sessions across multiple threads, which was not possible in the prior
118+
implementation.
129119

130120

131121
Password Encryption
132122
-------------------
133-
The DynECT REST API only accepts passwords in plain text, and currently there is
134-
no way around that. However, for those of you that are particularly mindful of
135-
security (and even those of you who aren't) can probably see some serious pitfalls
136-
to this. As far as most users of this library are concerned the passwords stored in
137-
their :class:`~dyn.tm.session.DynectSession` objects will only ever live in memory,
138-
so it's really not a huge deal that their passwords are stored in plain text. However,
139-
for users looking to do more advanced things, such as serialize and store their session
140-
objects in something less secure, such as a database, then these plain text passwords
141-
are far less than ideal. Because of this in version 1.1.0 we've added optional
142-
AES-256 password encryption for all :class:`~dyn.tm.session.DynectSession`
143-
instances. All you need to do to enable password encryption is install
144-
`PyCrypto <http://www.dlitz.net/software/pycrypto/>`_. The rest will happen
145-
automatically.
123+
The Managed DNS REST API only accepts passwords in plain text. The
124+
passwords stored in :class:`~dyn.tm.session.DynectSession` objects only
125+
live in memory, reducing the security risk of plain text passwords in this instance.
126+
However, for users looking to do more advanced things, such as serialize and store
127+
their session objects in something less secure, such as a database, these
128+
plain text passwords are not ideal. In response to this, Dyn added optional AES-256
129+
password encryption for all :class:`~dyn.tm.session.DynectSession` instances in
130+
version 1.1.0. To enable password encryption, install
131+
`PyCrypto <http://www.dlitz.net/software/pycrypto/>`_.
146132

147133
Key Generation
148134
^^^^^^^^^^^^^^
149-
Also in version 1.1.0 an optional key field parameter was added to the
135+
In version 1.1.0, an optional key field parameter was added to the
150136
:class:`~dyn.tm.session.DynectSession` __init__ method. This field will allow
151-
you to specify the key that your password will be encrypted using. However,
152-
you may also choose to let the dyn module handle the key generation for you as
153-
well using the :func:`~dyn.encrypt.generate_key` function which generates a,
154-
nearly, random 50 character key that can be easily consumed by the
155-
:class:`~dyn.encrypt.AESCipher` class (the class responsible for performing
156-
the actual encryption and decryption.
137+
you to specify the key that your encrypted password will be using. You can also
138+
let the Dyn module handle the key generation in addition to using
139+
the :func:`~dyn.encrypt.generate_key` function, which generates a random
140+
50 character key that can be easily consumed by the :class:`~dyn.encrypt.AESCipher`
141+
class (the class responsible for performing the encryption and decryption).
157142

158143
Encrypt Module
159144
^^^^^^^^^^^^^^
145+
::
160146
.. autofunction:: dyn.encrypt.generate_key
161147

162148
.. autoclass:: dyn.encrypt.AESCipher

docs/core.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
Core
44
====
55
The :mod:`dyn.core` module contains functionality that is core to the behavior
6-
of the rest of the library. In particular this is where a lot of the "heavy lifting"
6+
of the rest of the library. This is where a lot of the "heavy lifting"
77
for sessions is done.
88

99

docs/install.rst

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,37 +3,39 @@
33
Installation
44
============
55

6-
This part of the documentation covers the installation of the dyn module.
7-
The first step to using any software package is getting it properly installed.
6+
This part of the documentation covers the installation of the Dyn module.
87

98

109
Distribute & Pip
1110
----------------
1211

13-
Installing dyn is simple via `pip <http://www.pip-installer.org/>`_.
12+
The easiest way to install the Dyn module is via ‘pip’.
13+
14+
1. Go to <http://www.pip-installer.org/>’, download and install ‘pip’.
15+
2. In Terminal, run:
1416

1517
$ pip install dyn
1618

1719
Get the Code
1820
------------
1921

20-
dyn is actively developed on GitHub, the code is
21-
`always available <https://github.com/dyninc/dyn-python>`_.
22+
Dyn is actively developed on GitHub, the code is always available
23+
''<https://github.com/dyninc/dyn-python>` and there are several options
24+
available to obtain the code.
2225

23-
You can either clone the public repository::
26+
Clone the public repository::
2427

2528
git clone https://github.com/dyninc/dyn-python.git
2629

2730
Download the `tarball <https://github.com/dyninc/dyn-python/tarball/master>`_::
2831

2932
$ curl -OL https://github.com/dyninc/dyn-python/tarball/master
3033

31-
Or, download the `zipball <https://github.com/dyninc/dyn-python/zipball/master>`_::
34+
Download the `zipball <https://github.com/dyninc/dyn-python/zipball/master>`_::
3235

3336
$ curl -OL https://github.com/dyninc/dyn-python/zipball/master
3437

3538
Once you have a copy of the source, you can embed it in your Python package,
3639
or install it into your site-packages by running::
3740

3841
$ python setup.py install
39-

0 commit comments

Comments
 (0)