├── .gitattributes ├── .gitignore ├── README.md ├── docs-src ├── conf.py └── index.rst ├── docs ├── .buildinfo ├── .doctrees │ ├── environment.pickle │ └── index.doctree ├── .nojekyll ├── _modules │ ├── index.html │ └── requests_arcgis_auth │ │ ├── arcgis_auth.html │ │ ├── arcgis_exceptions.html │ │ ├── arcgis_saml_auth.html │ │ └── arcgis_token_auth.html ├── _sources │ └── index.rst.txt ├── _static │ ├── ajax-loader.gif │ ├── alabaster.css │ ├── basic.css │ ├── classic.css │ ├── comment-bright.png │ ├── comment-close.png │ ├── comment.png │ ├── custom.css │ ├── doctools.js │ ├── documentation_options.js │ ├── down-pressed.png │ ├── down.png │ ├── file.png │ ├── jquery-3.2.1.js │ ├── jquery.js │ ├── minus.png │ ├── plus.png │ ├── pygments.css │ ├── searchtools.js │ ├── sidebar.js │ ├── underscore-1.3.1.js │ ├── underscore.js │ ├── up-pressed.png │ ├── up.png │ └── websupport.js ├── genindex.html ├── index.html ├── objects.inv ├── py-modindex.html ├── search.html └── searchindex.js ├── requests_arcgis_auth ├── __init__.py ├── arcgis_auth.py ├── arcgis_exceptions.py ├── arcgis_saml_auth.py ├── arcgis_token_auth.py └── test │ ├── __init__.py │ ├── packages │ └── colorama-0.3.9 │ │ ├── CHANGELOG.rst │ │ ├── LICENSE.txt │ │ ├── MANIFEST.in │ │ ├── PKG-INFO │ │ ├── README.rst │ │ ├── colorama.egg-info │ │ ├── PKG-INFO │ │ ├── SOURCES.txt │ │ ├── dependency_links.txt │ │ ├── pbr.json │ │ └── top_level.txt │ │ ├── colorama │ │ ├── __init__.py │ │ ├── ansi.py │ │ ├── ansitowin32.py │ │ ├── initialise.py │ │ ├── win32.py │ │ └── winterm.py │ │ ├── demos │ │ ├── demo.bat │ │ ├── demo.sh │ │ ├── demo01.py │ │ ├── demo02.py │ │ ├── demo03.py │ │ ├── demo04.py │ │ ├── demo05.py │ │ ├── demo06.py │ │ ├── demo07.py │ │ ├── demo08.py │ │ └── fixpath.py │ │ ├── setup.cfg │ │ └── setup.py │ ├── test.cfg │ └── test_arcgis_auth.py ├── requirements.txt └── setup.py /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Esri ArcGIS Authentication Handlers for Python Requests API 2 | 3 | **Authenticate to Esri ArcGIS for Server, Portal and ArcGIS Online (AGOL) using Python Requests** 4 | 5 | ---------- 6 | 7 | This module provides python requests authentication handlers for the Esri ArcGIS Server and Portal products. The purpose is to authenticate a user to obtain authorized access to protected data and functions in the Esri REST API. There are endless use cases to automate business or IT administrative workflows... here are a few examples: 8 | 1) Automate user management (creating/removing users or modifying users roles/permissions) 9 | 2) Automate service publishing 10 | 3) Completing geospatial data analysis (for protected services) 11 | 12 | The authentication handlers support the following deployment models: 13 | 14 | * Propritery ‘Token-Based’ Authentication 15 | * Web-Tier security using NTLM or Kerberos (Microsoft Integrated Windows Authentication) 16 | * SAML based ‘enterprise logins’ (OAuth2)\* 17 | 18 | *Only supports SAML services with Kerberos authentication (no forms based login) 19 | 20 | More information and examples can be found at - https://doi-blm.github.io/requests-arcgis-auth/ 21 | 22 | ## Basic Usage Examples: 23 | 24 | ArcGIS for Server "Token Authentication" Usage (Non-Session Based): 25 | ```python 26 | import requests 27 | from requests_arcgis_auth import ArcGISServerTokenAuth 28 | r = requests.get(r'https://host/arcgis/rest/services?f=json', auth=ArcGISServerTokenAuth(username,password)) 29 | ``` 30 | 31 | ArcGIS Online and Portal for ArcGIS "Token" Authentication Usage: 32 | ```python 33 | import requests 34 | from requests_arcgis_auth import ArcGISPortalTokenAuth 35 | s=requests.Session() 36 | s.auth = ArcGISPortalTokenAuth(username,password) 37 | r = s.get(r'https://host/sharing/rest?f=json') 38 | ``` 39 | 40 | ArcGIS Online and Portal for ArcGIS "Enterprise Logins via SAML" Authentication Usage: 41 | ```python 42 | import requests 43 | from requests_arcgis_auth import ArcGISPortalSAMLAuth 44 | 45 | client_id = "123456789" # This client_id is that of a registered 'application' in the portal. 46 | auth = ArcGISPortalSAMLAuth(client_id) 47 | 48 | s = requests.session() 49 | s.auth = auth 50 | s.get("https://org.maps.arcgis.com/sharing/rest/portals/self?f=json") 51 | ``` 52 | 53 | 54 | -------------------------------------------------------------------------------- /docs-src/conf.py: -------------------------------------------------------------------------------- 1 | 2 | import sys 3 | import os 4 | # Insert requests_arcgis_auth path into the system. 5 | sys.path.insert(0, os.path.abspath('..\..')) 6 | import requests_arcgis_auth 7 | 8 | # -*- coding: utf-8 -*- 9 | # 10 | # Configuration file for the Sphinx documentation builder. 11 | # 12 | # This file does only contain a selection of the most common options. For a 13 | # full list see the documentation: 14 | # http://www.sphinx-doc.org/en/stable/config 15 | 16 | # -- Path setup -------------------------------------------------------------- 17 | 18 | # If extensions (or modules to document with autodoc) are in another directory, 19 | # add these directories to sys.path here. If the directory is relative to the 20 | # documentation root, use os.path.abspath to make it absolute, like shown here. 21 | # 22 | # import os 23 | # import sys 24 | # sys.path.insert(0, os.path.abspath('.')) 25 | 26 | 27 | # -- Project information ----------------------------------------------------- 28 | 29 | project = u'requests_arcgis_auth' 30 | copyright = u'2018, USDOI BLM' 31 | author = u'USDOI BLM' 32 | 33 | # The short X.Y version 34 | version = u'' 35 | # The full version, including alpha/beta/rc tags 36 | release = u'1.0' 37 | 38 | 39 | # -- General configuration --------------------------------------------------- 40 | 41 | # If your documentation needs a minimal Sphinx version, state it here. 42 | # 43 | # needs_sphinx = '1.0' 44 | 45 | # Add any Sphinx extension module names here, as strings. They can be 46 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 47 | # ones. 48 | extensions = [ 49 | 'sphinx.ext.doctest', 50 | 'sphinx.ext.ifconfig', 51 | 'sphinx.ext.viewcode', 52 | 'sphinx.ext.githubpages', 53 | 'sphinx.ext.autodoc', 54 | 'sphinx.ext.napoleon' 55 | ] 56 | 57 | napoleon_google_docstring = True 58 | 59 | # Add any paths that contain templates here, relative to this directory. 60 | templates_path = ['_templates'] 61 | 62 | # The suffix(es) of source filenames. 63 | # You can specify multiple suffix as a list of string: 64 | # 65 | # source_suffix = ['.rst', '.md'] 66 | source_suffix = '.rst' 67 | 68 | # The master toctree document. 69 | master_doc = 'index' 70 | 71 | # The language for content autogenerated by Sphinx. Refer to documentation 72 | # for a list of supported languages. 73 | # 74 | # This is also used if you do content translation via gettext catalogs. 75 | # Usually you set "language" from the command line for these cases. 76 | language = None 77 | 78 | # List of patterns, relative to source directory, that match files and 79 | # directories to ignore when looking for source files. 80 | # This pattern also affects html_static_path and html_extra_path . 81 | exclude_patterns = [] 82 | 83 | # The name of the Pygments (syntax highlighting) style to use. 84 | pygments_style = 'sphinx' 85 | 86 | 87 | # -- Options for HTML output ------------------------------------------------- 88 | 89 | # The theme to use for HTML and HTML Help pages. See the documentation for 90 | # a list of builtin themes. 91 | # 92 | #html_theme = 'alabaster' 93 | html_theme = "classic" 94 | 95 | 96 | # Theme options are theme-specific and customize the look and feel of a theme 97 | # further. For a list of options available for each theme, see the 98 | # documentation. 99 | # 100 | # html_theme_options = {} 101 | 102 | # Add any paths that contain custom static files (such as style sheets) here, 103 | # relative to this directory. They are copied after the builtin static files, 104 | # so a file named "default.css" will overwrite the builtin "default.css". 105 | html_static_path = ['_static'] 106 | 107 | # Custom sidebar templates, must be a dictionary that maps document names 108 | # to template names. 109 | # 110 | # The default sidebars (for documents that don't match any pattern) are 111 | # defined by theme itself. Builtin themes are using these templates by 112 | # default: ``['localtoc.html', 'relations.html', 'sourcelink.html', 113 | # 'searchbox.html']``. 114 | # 115 | # html_sidebars = {} 116 | 117 | 118 | # -- Options for HTMLHelp output --------------------------------------------- 119 | 120 | # Output file base name for HTML help builder. 121 | htmlhelp_basename = 'requests_arcgis_authdoc' 122 | 123 | 124 | # -- Options for LaTeX output ------------------------------------------------ 125 | 126 | latex_elements = { 127 | # The paper size ('letterpaper' or 'a4paper'). 128 | # 129 | # 'papersize': 'letterpaper', 130 | 131 | # The font size ('10pt', '11pt' or '12pt'). 132 | # 133 | # 'pointsize': '10pt', 134 | 135 | # Additional stuff for the LaTeX preamble. 136 | # 137 | # 'preamble': '', 138 | 139 | # Latex figure (float) alignment 140 | # 141 | # 'figure_align': 'htbp', 142 | } 143 | 144 | # Grouping the document tree into LaTeX files. List of tuples 145 | # (source start file, target name, title, 146 | # author, documentclass [howto, manual, or own class]). 147 | latex_documents = [ 148 | (master_doc, 'requests_arcgis_auth.tex', u'requests\\_arcgis\\_auth Documentation', 149 | u'USDOI BLM', 'manual'), 150 | ] 151 | 152 | 153 | # -- Options for manual page output ------------------------------------------ 154 | 155 | # One entry per manual page. List of tuples 156 | # (source start file, name, description, authors, manual section). 157 | man_pages = [ 158 | (master_doc, 'requests_arcgis_auth', u'requests_arcgis_auth Documentation', 159 | [author], 1) 160 | ] 161 | 162 | 163 | # -- Options for Texinfo output ---------------------------------------------- 164 | 165 | # Grouping the document tree into Texinfo files. List of tuples 166 | # (source start file, target name, title, author, 167 | # dir menu entry, description, category) 168 | texinfo_documents = [ 169 | (master_doc, 'requests_arcgis_auth', u'requests_arcgis_auth Documentation', 170 | author, 'requests_arcgis_auth', 'One line description of project.', 171 | 'Miscellaneous'), 172 | ] 173 | 174 | 175 | # -- Options for Epub output ------------------------------------------------- 176 | 177 | # Bibliographic Dublin Core info. 178 | epub_title = project 179 | epub_author = author 180 | epub_publisher = author 181 | epub_copyright = copyright 182 | 183 | # The unique identifier of the text. This can be a ISBN number 184 | # or the project homepage. 185 | # 186 | # epub_identifier = '' 187 | 188 | # A unique identification for the text. 189 | # 190 | # epub_uid = '' 191 | 192 | # A list of files that should not be packed into the epub file. 193 | epub_exclude_files = ['search.html'] 194 | 195 | 196 | # -- Extension configuration ------------------------------------------------- -------------------------------------------------------------------------------- /docs-src/index.rst: -------------------------------------------------------------------------------- 1 | 2 | Welcome to requests_arcgis_auth's documentation! 3 | ================================================ 4 | 5 | .. toctree:: 6 | :maxdepth: 2 7 | :caption: Contents: 8 | 9 | Documentation & Code Samples 10 | ArcGISPortalSAMLAuth 11 | ArcGISServerAuth 12 | ArcGISPortalTokenAuth 13 | ArcGISServerTokenAuth 14 | 15 | 16 | A python :mod:`requests` API authentication handler for the Esri ArcGIS Server, Portal, and ArcGIS Online (AGOL) products 17 | 18 | **requests_arcgis_auth** allows you to authenticate to Esri ArcGIS for Server, 19 | Portal for ArcGIS and ArcGIS Online (AGOL). The authentication handlers support the 20 | following deployment models: 21 | 22 | * Propritery 'Token-Based' Authentication 23 | * Web-Tier security using NTLM or Kerberos (Microsoft Integrated Windows Authentication) 24 | * SAML based 'enterprise logins' (OAuth2)\* 25 | 26 | \*Only supports SAML services with Kerberos authentication (no forms based login) 27 | 28 | 29 | Indices and tables 30 | ================== 31 | 32 | * :ref:`genindex` 33 | * :ref:`modindex` 34 | * :ref:`search` 35 | 36 | Documentation & Code Samples 37 | ============================ 38 | 39 | ArcGISPortalSAMLAuth 40 | -------------------- 41 | .. autoclass:: requests_arcgis_auth.ArcGISPortalSAMLAuth 42 | 43 | The ArcGISPortalSAMLAuth authentication handler was developed to work with Portal 44 | and ArcGIS Online (AGOL) solutions (refereed to an 'Esri portal' from here on) 45 | that are federated to the Department of Interior (DOI) Security Assertion Markup 46 | Language (SAML) service. This is an implementation of the Esri "Enterprise Logins" 47 | feature of an Esri portal solution. The authentication to the DOI SAML service is 48 | setup to use requests-kerberos authentication with OPTIONAL Mutual Authentication. 49 | This handler could theoretically support other 3rd party SAML services, but has 50 | not been developed or tested for that purpose. 51 | 52 | The authentication handler was developed as an Authorization Code Grant 'User Login' 53 | and will require a *Client ID* of an Esri portal registered application. Further 54 | information of this login workflow can be found at http://resources.arcgis.com/en/help/arcgis-rest-api/index.html#/Authentication/02r30000009z000000/ 55 | 56 | Code Sample (Session Based): 57 | 58 | >>> import requests 59 | >>> from requests_arcgis_auth import ArcGISPortalSAMLAuth 60 | >>> s = requests.session() 61 | >>> s.auth = ArcGISPortalSAMLAuth(client_id) 62 | >>> r = s.get("https://org.maps.arcgis.com/sharing/rest/portals/self?f=json") 63 | >>> print ("logged in as {}".format(r.json().get('user').get('username'))) 64 | logged in as 65 | 66 | .. note:: The ArcGISPortalSAMLAuth handler requires the requests_kerberos, requests_ntlm and BeautifulSoup4 modules. 67 | 68 | ArcGISServerAuth 69 | ---------------- 70 | .. autoclass:: requests_arcgis_auth.ArcGISServerAuth 71 | 72 | **Token OR Web-tier (Kerberos/NTLM) Authentication Example ("General Handler")**--- 73 | The following will attempt to acquire a token and in the event of an HTTP Status 74 | Code 401 (un-authorized) it will inspect HTTP www-authenticate response headers 75 | for Kerberos and/or NTLM support. If the server supports Kerberos or NTLM the 76 | auth handler will attempt authentication with the appropriate security provider. 77 | 78 | >>> from requests_arcgis_auth import ArcGISServerAuth 79 | >>>auth = ArcGISServerAuth(username,password) 80 | 81 | **Kerberos Web-Tier Authentication Example**--- 82 | The users logged in identity can be leverated if the client, server, and 83 | underlying domain all support Kerberos single-sign-on. The advantage of 84 | this approach is that the user credentials do not need to be stored in memory. 85 | The example can be used if the underlying site is known to support Kerberos. 86 | 87 | >>> from requests_arcgis_auth import ArcGISServerAuth 88 | >>> auth = ArcGISServerAuth() 89 | 90 | 91 | ArcGISPortalTokenAuth 92 | --------------------- 93 | .. autoclass:: requests_arcgis_auth.ArcGISPortalTokenAuth 94 | 95 | **Kerberos Web-Tier Authentication Example** --- 96 | The users logged in identity can be leveraged if the client, server, and 97 | underlying domain all support Kerberos single-sign-on. The advantage of this 98 | approach is that the user credentials do not need to be stored in memory. 99 | The example can be used if the underlying site is known to support Kerberos. 100 | 101 | >>> from requests_arcgis_auth import ArcGISPortalAuth 102 | >>> auth = ArcGISPortalAuth() 103 | 104 | **Token OR Web-tier (Kerberos/NTLM) Authentication Example ("General Handler")**--- 105 | The following will attempt to acquire a token and in the event of an HTTP Status 106 | Code 401 (un-authorized) it will inspect HTTP www-authenticate response headers 107 | for Kerberos and/or NTLM support. If the server supports Kerberos or NTLM the 108 | auth handler will attempt authentication with the appropriate security provider. 109 | 110 | >>> from requests_arcgis_auth import ArcGISPortalAuth 111 | >>> auth = ArcGISPortalAuth(username,password) 112 | 113 | ArcGISServerTokenAuth 114 | --------------------- 115 | .. autoclass:: requests_arcgis_auth.ArcGISServerTokenAuth 116 | 117 | 118 | Exceptions 119 | ---------- 120 | .. autoexception:: requests_arcgis_auth.TokenAuthenticationError 121 | .. autoexception:: requests_arcgis_auth.TokenAuthenticationWarning 122 | 123 | 124 | 125 | References 126 | =================== 127 | Information about the Esri ArcGIS for Server Token authentication can be found 128 | at: http://server.arcgis.com/en/server/latest/administer/windows/about-arcgis-tokens.htm 129 | 130 | Information about the Esri Portal for ArcGIS Token Authentication can be found 131 | at: http://resources.arcgis.com/en/help/arcgis-rest-api/index.html#/Generate_Token/02r3000000m5000000/ 132 | 133 | Information on python requests can be found at: http://docs.python-requests.org/en/master/ 134 | 135 | OAuth2 via SAML authentication was developed based on https://www.prowestgis.com/there-and-back-again/ 136 | 137 | The authentication handlers were developed and tested using the standard python installation bundled with Esri ArcGIS for Desktop 10.3.1 (2.7.8) and the requests API. -------------------------------------------------------------------------------- /docs/.buildinfo: -------------------------------------------------------------------------------- 1 | # Sphinx build info version 1 2 | # This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. 3 | config: a700f69182226837bdaa0f6927645304 4 | tags: 645f666f9bcd5a90fca523b33c5a78b7 5 | -------------------------------------------------------------------------------- /docs/.doctrees/environment.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DOI-BLM/requests-arcgis-auth/e01c7b708638562efebb67b54a1f8a3bbcd1eff0/docs/.doctrees/environment.pickle -------------------------------------------------------------------------------- /docs/.doctrees/index.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DOI-BLM/requests-arcgis-auth/e01c7b708638562efebb67b54a1f8a3bbcd1eff0/docs/.doctrees/index.doctree -------------------------------------------------------------------------------- /docs/.nojekyll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DOI-BLM/requests-arcgis-auth/e01c7b708638562efebb67b54a1f8a3bbcd1eff0/docs/.nojekyll -------------------------------------------------------------------------------- /docs/_modules/index.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | Overview: module code — requests_arcgis_auth 1.0 documentation 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 28 | 29 |
30 |
31 |
32 | 42 |
43 |
44 | 60 |
61 |
62 | 71 | 75 | 76 | -------------------------------------------------------------------------------- /docs/_modules/requests_arcgis_auth/arcgis_exceptions.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | requests_arcgis_auth.arcgis_exceptions — requests_arcgis_auth 1.0 documentation 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 29 | 30 |
31 |
32 |
33 |
34 | 35 |

Source code for requests_arcgis_auth.arcgis_exceptions

36 | from requests.exceptions import RequestException,RequestsWarning
37 | 
38 | 
[docs]class TokenAuthenticationError(RequestException): 39 | """Site Does Not Support Token Authentication"""
40 | pass 41 | 42 |
[docs]class TokenAuthenticationWarning(RequestsWarning): 43 | """Site Does Not Support Token Authentication"""
44 | pass 45 |
46 | 47 |
48 |
49 |
50 | 66 |
67 |
68 | 78 | 82 | 83 | -------------------------------------------------------------------------------- /docs/_sources/index.rst.txt: -------------------------------------------------------------------------------- 1 | 2 | Welcome to requests_arcgis_auth's documentation! 3 | ================================================ 4 | 5 | .. toctree:: 6 | :maxdepth: 2 7 | :caption: Contents: 8 | 9 | Documentation & Code Samples 10 | ArcGISPortalSAMLAuth 11 | ArcGISServerAuth 12 | ArcGISPortalTokenAuth 13 | ArcGISServerTokenAuth 14 | 15 | 16 | A python :mod:`requests` API authentication handler for the Esri ArcGIS Server, Portal, and ArcGIS Online (AGOL) products 17 | 18 | **requests_arcgis_auth** allows you to authenticate to Esri ArcGIS for Server, 19 | Portal for ArcGIS and ArcGIS Online (AGOL). The authentication handlers support the 20 | following deployment models: 21 | 22 | * Propritery 'Token-Based' Authentication 23 | * Web-Tier security using NTLM or Kerberos (Microsoft Integrated Windows Authentication) 24 | * SAML based 'enterprise logins' (OAuth2)\* 25 | 26 | \*Only supports SAML services with Kerberos authentication (no forms based login) 27 | 28 | 29 | Indices and tables 30 | ================== 31 | 32 | * :ref:`genindex` 33 | * :ref:`modindex` 34 | * :ref:`search` 35 | 36 | Documentation & Code Samples 37 | ============================ 38 | 39 | ArcGISPortalSAMLAuth 40 | -------------------- 41 | .. autoclass:: requests_arcgis_auth.ArcGISPortalSAMLAuth 42 | 43 | The ArcGISPortalSAMLAuth authentication handler was developed to work with Portal 44 | and ArcGIS Online (AGOL) solutions (refereed to an 'Esri portal' from here on) 45 | that are federated to the Department of Interior (DOI) Security Assertion Markup 46 | Language (SAML) service. This is an implementation of the Esri "Enterprise Logins" 47 | feature of an Esri portal solution. The authentication to the DOI SAML service is 48 | setup to use requests-kerberos authentication with OPTIONAL Mutual Authentication. 49 | This handler could theoretically support other 3rd party SAML services, but has 50 | not been developed or tested for that purpose. 51 | 52 | The authentication handler was developed as an Authorization Code Grant 'User Login' 53 | and will require a *Client ID* of an Esri portal registered application. Further 54 | information of this login workflow can be found at http://resources.arcgis.com/en/help/arcgis-rest-api/index.html#/Authentication/02r30000009z000000/ 55 | 56 | Code Sample (Session Based): 57 | 58 | >>> import requests 59 | >>> from requests_arcgis_auth import ArcGISPortalSAMLAuth 60 | >>> s = requests.session() 61 | >>> s.auth = ArcGISPortalSAMLAuth(client_id) 62 | >>> r = s.get("https://org.maps.arcgis.com/sharing/rest/portals/self?f=json") 63 | >>> print ("logged in as {}".format(r.json().get('user').get('username'))) 64 | logged in as 65 | 66 | .. note:: The ArcGISPortalSAMLAuth handler requires the requests_kerberos, requests_ntlm and BeautifulSoup4 modules. 67 | 68 | ArcGISServerAuth 69 | ---------------- 70 | .. autoclass:: requests_arcgis_auth.ArcGISServerAuth 71 | 72 | **Token OR Web-tier (Kerberos/NTLM) Authentication Example ("General Handler")**--- 73 | The following will attempt to acquire a token and in the event of an HTTP Status 74 | Code 401 (un-authorized) it will inspect HTTP www-authenticate response headers 75 | for Kerberos and/or NTLM support. If the server supports Kerberos or NTLM the 76 | auth handler will attempt authentication with the appropriate security provider. 77 | 78 | >>> from requests_arcgis_auth import ArcGISServerAuth 79 | >>>auth = ArcGISServerAuth(username,password) 80 | 81 | **Kerberos Web-Tier Authentication Example**--- 82 | The users logged in identity can be leverated if the client, server, and 83 | underlying domain all support Kerberos single-sign-on. The advantage of 84 | this approach is that the user credentials do not need to be stored in memory. 85 | The example can be used if the underlying site is known to support Kerberos. 86 | 87 | >>> from requests_arcgis_auth import ArcGISServerAuth 88 | >>> auth = ArcGISServerAuth() 89 | 90 | 91 | ArcGISPortalTokenAuth 92 | --------------------- 93 | .. autoclass:: requests_arcgis_auth.ArcGISPortalTokenAuth 94 | 95 | **Kerberos Web-Tier Authentication Example** --- 96 | The users logged in identity can be leveraged if the client, server, and 97 | underlying domain all support Kerberos single-sign-on. The advantage of this 98 | approach is that the user credentials do not need to be stored in memory. 99 | The example can be used if the underlying site is known to support Kerberos. 100 | 101 | >>> from requests_arcgis_auth import ArcGISPortalAuth 102 | >>> auth = ArcGISPortalAuth() 103 | 104 | **Token OR Web-tier (Kerberos/NTLM) Authentication Example ("General Handler")**--- 105 | The following will attempt to acquire a token and in the event of an HTTP Status 106 | Code 401 (un-authorized) it will inspect HTTP www-authenticate response headers 107 | for Kerberos and/or NTLM support. If the server supports Kerberos or NTLM the 108 | auth handler will attempt authentication with the appropriate security provider. 109 | 110 | >>> from requests_arcgis_auth import ArcGISPortalAuth 111 | >>> auth = ArcGISPortalAuth(username,password) 112 | 113 | ArcGISServerTokenAuth 114 | --------------------- 115 | .. autoclass:: requests_arcgis_auth.ArcGISServerTokenAuth 116 | 117 | 118 | Exceptions 119 | ---------- 120 | .. autoexception:: requests_arcgis_auth.TokenAuthenticationError 121 | .. autoexception:: requests_arcgis_auth.TokenAuthenticationWarning 122 | 123 | 124 | 125 | References 126 | =================== 127 | Information about the Esri ArcGIS for Server Token authentication can be found 128 | at: http://server.arcgis.com/en/server/latest/administer/windows/about-arcgis-tokens.htm 129 | 130 | Information about the Esri Portal for ArcGIS Token Authentication can be found 131 | at: http://resources.arcgis.com/en/help/arcgis-rest-api/index.html#/Generate_Token/02r3000000m5000000/ 132 | 133 | Information on python requests can be found at: http://docs.python-requests.org/en/master/ 134 | 135 | OAuth2 via SAML authentication was developed based on https://www.prowestgis.com/there-and-back-again/ 136 | 137 | The authentication handlers were developed and tested using the standard python installation bundled with Esri ArcGIS for Desktop 10.3.1 (2.7.8) and the requests API. -------------------------------------------------------------------------------- /docs/_static/ajax-loader.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DOI-BLM/requests-arcgis-auth/e01c7b708638562efebb67b54a1f8a3bbcd1eff0/docs/_static/ajax-loader.gif -------------------------------------------------------------------------------- /docs/_static/alabaster.css: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | @import url("basic.css"); 54 | 55 | /* -- page layout ----------------------------------------------------------- */ 56 | 57 | body { 58 | font-family: 'goudy old style', 'minion pro', 'bell mt', Georgia, 'Hiragino Mincho Pro', serif; 59 | font-size: 17px; 60 | background-color: #fff; 61 | color: #000; 62 | margin: 0; 63 | padding: 0; 64 | } 65 | 66 | 67 | div.document { 68 | width: 940px; 69 | margin: 30px auto 0 auto; 70 | } 71 | 72 | div.documentwrapper { 73 | float: left; 74 | width: 100%; 75 | } 76 | 77 | div.bodywrapper { 78 | margin: 0 0 0 220px; 79 | } 80 | 81 | div.sphinxsidebar { 82 | width: 220px; 83 | font-size: 14px; 84 | line-height: 1.5; 85 | } 86 | 87 | hr { 88 | border: 1px solid #B1B4B6; 89 | } 90 | 91 | div.body { 92 | background-color: #fff; 93 | color: #3E4349; 94 | padding: 0 30px 0 30px; 95 | } 96 | 97 | div.body > .section { 98 | text-align: left; 99 | } 100 | 101 | div.footer { 102 | width: 940px; 103 | margin: 20px auto 30px auto; 104 | font-size: 14px; 105 | color: #888; 106 | text-align: right; 107 | } 108 | 109 | div.footer a { 110 | color: #888; 111 | } 112 | 113 | p.caption { 114 | font-family: inherit; 115 | font-size: inherit; 116 | } 117 | 118 | 119 | div.relations { 120 | display: none; 121 | } 122 | 123 | 124 | div.sphinxsidebar a { 125 | color: #444; 126 | text-decoration: none; 127 | border-bottom: 1px dotted #999; 128 | } 129 | 130 | div.sphinxsidebar a:hover { 131 | border-bottom: 1px solid #999; 132 | } 133 | 134 | div.sphinxsidebarwrapper { 135 | padding: 18px 10px; 136 | } 137 | 138 | div.sphinxsidebarwrapper p.logo { 139 | padding: 0; 140 | margin: -10px 0 0 0px; 141 | text-align: center; 142 | } 143 | 144 | div.sphinxsidebarwrapper h1.logo { 145 | margin-top: -10px; 146 | text-align: center; 147 | margin-bottom: 5px; 148 | text-align: left; 149 | } 150 | 151 | div.sphinxsidebarwrapper h1.logo-name { 152 | margin-top: 0px; 153 | } 154 | 155 | div.sphinxsidebarwrapper p.blurb { 156 | margin-top: 0; 157 | font-style: normal; 158 | } 159 | 160 | div.sphinxsidebar h3, 161 | div.sphinxsidebar h4 { 162 | font-family: 'Garamond', 'Georgia', serif; 163 | color: #444; 164 | font-size: 24px; 165 | font-weight: normal; 166 | margin: 0 0 5px 0; 167 | padding: 0; 168 | } 169 | 170 | div.sphinxsidebar h4 { 171 | font-size: 20px; 172 | } 173 | 174 | div.sphinxsidebar h3 a { 175 | color: #444; 176 | } 177 | 178 | div.sphinxsidebar p.logo a, 179 | div.sphinxsidebar h3 a, 180 | div.sphinxsidebar p.logo a:hover, 181 | div.sphinxsidebar h3 a:hover { 182 | border: none; 183 | } 184 | 185 | div.sphinxsidebar p { 186 | color: #555; 187 | margin: 10px 0; 188 | } 189 | 190 | div.sphinxsidebar ul { 191 | margin: 10px 0; 192 | padding: 0; 193 | color: #000; 194 | } 195 | 196 | div.sphinxsidebar ul li.toctree-l1 > a { 197 | font-size: 120%; 198 | } 199 | 200 | div.sphinxsidebar ul li.toctree-l2 > a { 201 | font-size: 110%; 202 | } 203 | 204 | div.sphinxsidebar input { 205 | border: 1px solid #CCC; 206 | font-family: 'goudy old style', 'minion pro', 'bell mt', Georgia, 'Hiragino Mincho Pro', serif; 207 | font-size: 1em; 208 | } 209 | 210 | div.sphinxsidebar hr { 211 | border: none; 212 | height: 1px; 213 | color: #AAA; 214 | background: #AAA; 215 | 216 | text-align: left; 217 | margin-left: 0; 218 | width: 50%; 219 | } 220 | 221 | /* -- body styles ----------------------------------------------------------- */ 222 | 223 | a { 224 | color: #004B6B; 225 | text-decoration: underline; 226 | } 227 | 228 | a:hover { 229 | color: #6D4100; 230 | text-decoration: underline; 231 | } 232 | 233 | div.body h1, 234 | div.body h2, 235 | div.body h3, 236 | div.body h4, 237 | div.body h5, 238 | div.body h6 { 239 | font-family: 'Garamond', 'Georgia', serif; 240 | font-weight: normal; 241 | margin: 30px 0px 10px 0px; 242 | padding: 0; 243 | } 244 | 245 | div.body h1 { margin-top: 0; padding-top: 0; font-size: 240%; } 246 | div.body h2 { font-size: 180%; } 247 | div.body h3 { font-size: 150%; } 248 | div.body h4 { font-size: 130%; } 249 | div.body h5 { font-size: 100%; } 250 | div.body h6 { font-size: 100%; } 251 | 252 | a.headerlink { 253 | color: #DDD; 254 | padding: 0 4px; 255 | text-decoration: none; 256 | } 257 | 258 | a.headerlink:hover { 259 | color: #444; 260 | background: #EAEAEA; 261 | } 262 | 263 | div.body p, div.body dd, div.body li { 264 | line-height: 1.4em; 265 | } 266 | 267 | div.admonition { 268 | margin: 20px 0px; 269 | padding: 10px 30px; 270 | background-color: #EEE; 271 | border: 1px solid #CCC; 272 | } 273 | 274 | div.admonition tt.xref, div.admonition code.xref, div.admonition a tt { 275 | background-color: #FBFBFB; 276 | border-bottom: 1px solid #fafafa; 277 | } 278 | 279 | div.admonition p.admonition-title { 280 | font-family: 'Garamond', 'Georgia', serif; 281 | font-weight: normal; 282 | font-size: 24px; 283 | margin: 0 0 10px 0; 284 | padding: 0; 285 | line-height: 1; 286 | } 287 | 288 | div.admonition p.last { 289 | margin-bottom: 0; 290 | } 291 | 292 | div.highlight { 293 | background-color: #fff; 294 | } 295 | 296 | dt:target, .highlight { 297 | background: #FAF3E8; 298 | } 299 | 300 | div.warning { 301 | background-color: #FCC; 302 | border: 1px solid #FAA; 303 | } 304 | 305 | div.danger { 306 | background-color: #FCC; 307 | border: 1px solid #FAA; 308 | -moz-box-shadow: 2px 2px 4px #D52C2C; 309 | -webkit-box-shadow: 2px 2px 4px #D52C2C; 310 | box-shadow: 2px 2px 4px #D52C2C; 311 | } 312 | 313 | div.error { 314 | background-color: #FCC; 315 | border: 1px solid #FAA; 316 | -moz-box-shadow: 2px 2px 4px #D52C2C; 317 | -webkit-box-shadow: 2px 2px 4px #D52C2C; 318 | box-shadow: 2px 2px 4px #D52C2C; 319 | } 320 | 321 | div.caution { 322 | background-color: #FCC; 323 | border: 1px solid #FAA; 324 | } 325 | 326 | div.attention { 327 | background-color: #FCC; 328 | border: 1px solid #FAA; 329 | } 330 | 331 | div.important { 332 | background-color: #EEE; 333 | border: 1px solid #CCC; 334 | } 335 | 336 | div.note { 337 | background-color: #EEE; 338 | border: 1px solid #CCC; 339 | } 340 | 341 | div.tip { 342 | background-color: #EEE; 343 | border: 1px solid #CCC; 344 | } 345 | 346 | div.hint { 347 | background-color: #EEE; 348 | border: 1px solid #CCC; 349 | } 350 | 351 | div.seealso { 352 | background-color: #EEE; 353 | border: 1px solid #CCC; 354 | } 355 | 356 | div.topic { 357 | background-color: #EEE; 358 | } 359 | 360 | p.admonition-title { 361 | display: inline; 362 | } 363 | 364 | p.admonition-title:after { 365 | content: ":"; 366 | } 367 | 368 | pre, tt, code { 369 | font-family: 'Consolas', 'Menlo', 'Deja Vu Sans Mono', 'Bitstream Vera Sans Mono', monospace; 370 | font-size: 0.9em; 371 | } 372 | 373 | .hll { 374 | background-color: #FFC; 375 | margin: 0 -12px; 376 | padding: 0 12px; 377 | display: block; 378 | } 379 | 380 | img.screenshot { 381 | } 382 | 383 | tt.descname, tt.descclassname, code.descname, code.descclassname { 384 | font-size: 0.95em; 385 | } 386 | 387 | tt.descname, code.descname { 388 | padding-right: 0.08em; 389 | } 390 | 391 | img.screenshot { 392 | -moz-box-shadow: 2px 2px 4px #EEE; 393 | -webkit-box-shadow: 2px 2px 4px #EEE; 394 | box-shadow: 2px 2px 4px #EEE; 395 | } 396 | 397 | table.docutils { 398 | border: 1px solid #888; 399 | -moz-box-shadow: 2px 2px 4px #EEE; 400 | -webkit-box-shadow: 2px 2px 4px #EEE; 401 | box-shadow: 2px 2px 4px #EEE; 402 | } 403 | 404 | table.docutils td, table.docutils th { 405 | border: 1px solid #888; 406 | padding: 0.25em 0.7em; 407 | } 408 | 409 | table.field-list, table.footnote { 410 | border: none; 411 | -moz-box-shadow: none; 412 | -webkit-box-shadow: none; 413 | box-shadow: none; 414 | } 415 | 416 | table.footnote { 417 | margin: 15px 0; 418 | width: 100%; 419 | border: 1px solid #EEE; 420 | background: #FDFDFD; 421 | font-size: 0.9em; 422 | } 423 | 424 | table.footnote + table.footnote { 425 | margin-top: -15px; 426 | border-top: none; 427 | } 428 | 429 | table.field-list th { 430 | padding: 0 0.8em 0 0; 431 | } 432 | 433 | table.field-list td { 434 | padding: 0; 435 | } 436 | 437 | table.field-list p { 438 | margin-bottom: 0.8em; 439 | } 440 | 441 | /* Cloned from 442 | * https://github.com/sphinx-doc/sphinx/commit/ef60dbfce09286b20b7385333d63a60321784e68 443 | */ 444 | .field-name { 445 | -moz-hyphens: manual; 446 | -ms-hyphens: manual; 447 | -webkit-hyphens: manual; 448 | hyphens: manual; 449 | } 450 | 451 | table.footnote td.label { 452 | width: .1px; 453 | padding: 0.3em 0 0.3em 0.5em; 454 | } 455 | 456 | table.footnote td { 457 | padding: 0.3em 0.5em; 458 | } 459 | 460 | dl { 461 | margin: 0; 462 | padding: 0; 463 | } 464 | 465 | dl dd { 466 | margin-left: 30px; 467 | } 468 | 469 | blockquote { 470 | margin: 0 0 0 30px; 471 | padding: 0; 472 | } 473 | 474 | ul, ol { 475 | /* Matches the 30px from the narrow-screen "li > ul" selector below */ 476 | margin: 10px 0 10px 30px; 477 | padding: 0; 478 | } 479 | 480 | pre { 481 | background: #EEE; 482 | padding: 7px 30px; 483 | margin: 15px 0px; 484 | line-height: 1.3em; 485 | } 486 | 487 | div.viewcode-block:target { 488 | background: #ffd; 489 | } 490 | 491 | dl pre, blockquote pre, li pre { 492 | margin-left: 0; 493 | padding-left: 30px; 494 | } 495 | 496 | tt, code { 497 | background-color: #ecf0f3; 498 | color: #222; 499 | /* padding: 1px 2px; */ 500 | } 501 | 502 | tt.xref, code.xref, a tt { 503 | background-color: #FBFBFB; 504 | border-bottom: 1px solid #fff; 505 | } 506 | 507 | a.reference { 508 | text-decoration: none; 509 | border-bottom: 1px dotted #004B6B; 510 | } 511 | 512 | /* Don't put an underline on images */ 513 | a.image-reference, a.image-reference:hover { 514 | border-bottom: none; 515 | } 516 | 517 | a.reference:hover { 518 | border-bottom: 1px solid #6D4100; 519 | } 520 | 521 | a.footnote-reference { 522 | text-decoration: none; 523 | font-size: 0.7em; 524 | vertical-align: top; 525 | border-bottom: 1px dotted #004B6B; 526 | } 527 | 528 | a.footnote-reference:hover { 529 | border-bottom: 1px solid #6D4100; 530 | } 531 | 532 | a:hover tt, a:hover code { 533 | background: #EEE; 534 | } 535 | 536 | 537 | @media screen and (max-width: 870px) { 538 | 539 | div.sphinxsidebar { 540 | display: none; 541 | } 542 | 543 | div.document { 544 | width: 100%; 545 | 546 | } 547 | 548 | div.documentwrapper { 549 | margin-left: 0; 550 | margin-top: 0; 551 | margin-right: 0; 552 | margin-bottom: 0; 553 | } 554 | 555 | div.bodywrapper { 556 | margin-top: 0; 557 | margin-right: 0; 558 | margin-bottom: 0; 559 | margin-left: 0; 560 | } 561 | 562 | ul { 563 | margin-left: 0; 564 | } 565 | 566 | li > ul { 567 | /* Matches the 30px from the "ul, ol" selector above */ 568 | margin-left: 30px; 569 | } 570 | 571 | .document { 572 | width: auto; 573 | } 574 | 575 | .footer { 576 | width: auto; 577 | } 578 | 579 | .bodywrapper { 580 | margin: 0; 581 | } 582 | 583 | .footer { 584 | width: auto; 585 | } 586 | 587 | .github { 588 | display: none; 589 | } 590 | 591 | 592 | 593 | } 594 | 595 | 596 | 597 | @media screen and (max-width: 875px) { 598 | 599 | body { 600 | margin: 0; 601 | padding: 20px 30px; 602 | } 603 | 604 | div.documentwrapper { 605 | float: none; 606 | background: #fff; 607 | } 608 | 609 | div.sphinxsidebar { 610 | display: block; 611 | float: none; 612 | width: 102.5%; 613 | margin: 50px -30px -20px -30px; 614 | padding: 10px 20px; 615 | background: #333; 616 | color: #FFF; 617 | } 618 | 619 | div.sphinxsidebar h3, div.sphinxsidebar h4, div.sphinxsidebar p, 620 | div.sphinxsidebar h3 a { 621 | color: #fff; 622 | } 623 | 624 | div.sphinxsidebar a { 625 | color: #AAA; 626 | } 627 | 628 | div.sphinxsidebar p.logo { 629 | display: none; 630 | } 631 | 632 | div.document { 633 | width: 100%; 634 | margin: 0; 635 | } 636 | 637 | div.footer { 638 | display: none; 639 | } 640 | 641 | div.bodywrapper { 642 | margin: 0; 643 | } 644 | 645 | div.body { 646 | min-height: 0; 647 | padding: 0; 648 | } 649 | 650 | .rtd_doc_footer { 651 | display: none; 652 | } 653 | 654 | .document { 655 | width: auto; 656 | } 657 | 658 | .footer { 659 | width: auto; 660 | } 661 | 662 | .footer { 663 | width: auto; 664 | } 665 | 666 | .github { 667 | display: none; 668 | } 669 | } 670 | 671 | 672 | /* misc. */ 673 | 674 | .revsys-inline { 675 | display: none!important; 676 | } 677 | 678 | /* Make nested-list/multi-paragraph items look better in Releases changelog 679 | * pages. Without this, docutils' magical list fuckery causes inconsistent 680 | * formatting between different release sub-lists. 681 | */ 682 | div#changelog > div.section > ul > li > p:only-child { 683 | margin-bottom: 0; 684 | } 685 | 686 | /* Hide fugly table cell borders in ..bibliography:: directive output */ 687 | table.docutils.citation, table.docutils.citation td, table.docutils.citation th { 688 | border: none; 689 | /* Below needed in some edge cases; if not applied, bottom shadows appear */ 690 | -moz-box-shadow: none; 691 | -webkit-box-shadow: none; 692 | box-shadow: none; 693 | } -------------------------------------------------------------------------------- /docs/_static/basic.css: -------------------------------------------------------------------------------- 1 | /* 2 | * basic.css 3 | * ~~~~~~~~~ 4 | * 5 | * Sphinx stylesheet -- basic theme. 6 | * 7 | * :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. 8 | * :license: BSD, see LICENSE for details. 9 | * 10 | */ 11 | 12 | /* -- main layout ----------------------------------------------------------- */ 13 | 14 | div.clearer { 15 | clear: both; 16 | } 17 | 18 | /* -- relbar ---------------------------------------------------------------- */ 19 | 20 | div.related { 21 | width: 100%; 22 | font-size: 90%; 23 | } 24 | 25 | div.related h3 { 26 | display: none; 27 | } 28 | 29 | div.related ul { 30 | margin: 0; 31 | padding: 0 0 0 10px; 32 | list-style: none; 33 | } 34 | 35 | div.related li { 36 | display: inline; 37 | } 38 | 39 | div.related li.right { 40 | float: right; 41 | margin-right: 5px; 42 | } 43 | 44 | /* -- sidebar --------------------------------------------------------------- */ 45 | 46 | div.sphinxsidebarwrapper { 47 | padding: 10px 5px 0 10px; 48 | } 49 | 50 | div.sphinxsidebar { 51 | float: left; 52 | width: 230px; 53 | margin-left: -100%; 54 | font-size: 90%; 55 | word-wrap: break-word; 56 | overflow-wrap : break-word; 57 | } 58 | 59 | div.sphinxsidebar ul { 60 | list-style: none; 61 | } 62 | 63 | div.sphinxsidebar ul ul, 64 | div.sphinxsidebar ul.want-points { 65 | margin-left: 20px; 66 | list-style: square; 67 | } 68 | 69 | div.sphinxsidebar ul ul { 70 | margin-top: 0; 71 | margin-bottom: 0; 72 | } 73 | 74 | div.sphinxsidebar form { 75 | margin-top: 10px; 76 | } 77 | 78 | div.sphinxsidebar input { 79 | border: 1px solid #98dbcc; 80 | font-family: sans-serif; 81 | font-size: 1em; 82 | } 83 | 84 | div.sphinxsidebar #searchbox input[type="text"] { 85 | float: left; 86 | width: 80%; 87 | padding: 0.25em; 88 | box-sizing: border-box; 89 | } 90 | 91 | div.sphinxsidebar #searchbox input[type="submit"] { 92 | float: left; 93 | width: 20%; 94 | border-left: none; 95 | padding: 0.25em; 96 | box-sizing: border-box; 97 | } 98 | 99 | 100 | img { 101 | border: 0; 102 | max-width: 100%; 103 | } 104 | 105 | /* -- search page ----------------------------------------------------------- */ 106 | 107 | ul.search { 108 | margin: 10px 0 0 20px; 109 | padding: 0; 110 | } 111 | 112 | ul.search li { 113 | padding: 5px 0 5px 20px; 114 | background-image: url(file.png); 115 | background-repeat: no-repeat; 116 | background-position: 0 7px; 117 | } 118 | 119 | ul.search li a { 120 | font-weight: bold; 121 | } 122 | 123 | ul.search li div.context { 124 | color: #888; 125 | margin: 2px 0 0 30px; 126 | text-align: left; 127 | } 128 | 129 | ul.keywordmatches li.goodmatch a { 130 | font-weight: bold; 131 | } 132 | 133 | /* -- index page ------------------------------------------------------------ */ 134 | 135 | table.contentstable { 136 | width: 90%; 137 | margin-left: auto; 138 | margin-right: auto; 139 | } 140 | 141 | table.contentstable p.biglink { 142 | line-height: 150%; 143 | } 144 | 145 | a.biglink { 146 | font-size: 1.3em; 147 | } 148 | 149 | span.linkdescr { 150 | font-style: italic; 151 | padding-top: 5px; 152 | font-size: 90%; 153 | } 154 | 155 | /* -- general index --------------------------------------------------------- */ 156 | 157 | table.indextable { 158 | width: 100%; 159 | } 160 | 161 | table.indextable td { 162 | text-align: left; 163 | vertical-align: top; 164 | } 165 | 166 | table.indextable ul { 167 | margin-top: 0; 168 | margin-bottom: 0; 169 | list-style-type: none; 170 | } 171 | 172 | table.indextable > tbody > tr > td > ul { 173 | padding-left: 0em; 174 | } 175 | 176 | table.indextable tr.pcap { 177 | height: 10px; 178 | } 179 | 180 | table.indextable tr.cap { 181 | margin-top: 10px; 182 | background-color: #f2f2f2; 183 | } 184 | 185 | img.toggler { 186 | margin-right: 3px; 187 | margin-top: 3px; 188 | cursor: pointer; 189 | } 190 | 191 | div.modindex-jumpbox { 192 | border-top: 1px solid #ddd; 193 | border-bottom: 1px solid #ddd; 194 | margin: 1em 0 1em 0; 195 | padding: 0.4em; 196 | } 197 | 198 | div.genindex-jumpbox { 199 | border-top: 1px solid #ddd; 200 | border-bottom: 1px solid #ddd; 201 | margin: 1em 0 1em 0; 202 | padding: 0.4em; 203 | } 204 | 205 | /* -- domain module index --------------------------------------------------- */ 206 | 207 | table.modindextable td { 208 | padding: 2px; 209 | border-collapse: collapse; 210 | } 211 | 212 | /* -- general body styles --------------------------------------------------- */ 213 | 214 | div.body { 215 | min-width: 450px; 216 | max-width: 800px; 217 | } 218 | 219 | div.body p, div.body dd, div.body li, div.body blockquote { 220 | -moz-hyphens: auto; 221 | -ms-hyphens: auto; 222 | -webkit-hyphens: auto; 223 | hyphens: auto; 224 | } 225 | 226 | a.headerlink { 227 | visibility: hidden; 228 | } 229 | 230 | h1:hover > a.headerlink, 231 | h2:hover > a.headerlink, 232 | h3:hover > a.headerlink, 233 | h4:hover > a.headerlink, 234 | h5:hover > a.headerlink, 235 | h6:hover > a.headerlink, 236 | dt:hover > a.headerlink, 237 | caption:hover > a.headerlink, 238 | p.caption:hover > a.headerlink, 239 | div.code-block-caption:hover > a.headerlink { 240 | visibility: visible; 241 | } 242 | 243 | div.body p.caption { 244 | text-align: inherit; 245 | } 246 | 247 | div.body td { 248 | text-align: left; 249 | } 250 | 251 | .first { 252 | margin-top: 0 !important; 253 | } 254 | 255 | p.rubric { 256 | margin-top: 30px; 257 | font-weight: bold; 258 | } 259 | 260 | img.align-left, .figure.align-left, object.align-left { 261 | clear: left; 262 | float: left; 263 | margin-right: 1em; 264 | } 265 | 266 | img.align-right, .figure.align-right, object.align-right { 267 | clear: right; 268 | float: right; 269 | margin-left: 1em; 270 | } 271 | 272 | img.align-center, .figure.align-center, object.align-center { 273 | display: block; 274 | margin-left: auto; 275 | margin-right: auto; 276 | } 277 | 278 | .align-left { 279 | text-align: left; 280 | } 281 | 282 | .align-center { 283 | text-align: center; 284 | } 285 | 286 | .align-right { 287 | text-align: right; 288 | } 289 | 290 | /* -- sidebars -------------------------------------------------------------- */ 291 | 292 | div.sidebar { 293 | margin: 0 0 0.5em 1em; 294 | border: 1px solid #ddb; 295 | padding: 7px 7px 0 7px; 296 | background-color: #ffe; 297 | width: 40%; 298 | float: right; 299 | } 300 | 301 | p.sidebar-title { 302 | font-weight: bold; 303 | } 304 | 305 | /* -- topics ---------------------------------------------------------------- */ 306 | 307 | div.topic { 308 | border: 1px solid #ccc; 309 | padding: 7px 7px 0 7px; 310 | margin: 10px 0 10px 0; 311 | } 312 | 313 | p.topic-title { 314 | font-size: 1.1em; 315 | font-weight: bold; 316 | margin-top: 10px; 317 | } 318 | 319 | /* -- admonitions ----------------------------------------------------------- */ 320 | 321 | div.admonition { 322 | margin-top: 10px; 323 | margin-bottom: 10px; 324 | padding: 7px; 325 | } 326 | 327 | div.admonition dt { 328 | font-weight: bold; 329 | } 330 | 331 | div.admonition dl { 332 | margin-bottom: 0; 333 | } 334 | 335 | p.admonition-title { 336 | margin: 0px 10px 5px 0px; 337 | font-weight: bold; 338 | } 339 | 340 | div.body p.centered { 341 | text-align: center; 342 | margin-top: 25px; 343 | } 344 | 345 | /* -- tables ---------------------------------------------------------------- */ 346 | 347 | table.docutils { 348 | border: 0; 349 | border-collapse: collapse; 350 | } 351 | 352 | table.align-center { 353 | margin-left: auto; 354 | margin-right: auto; 355 | } 356 | 357 | table caption span.caption-number { 358 | font-style: italic; 359 | } 360 | 361 | table caption span.caption-text { 362 | } 363 | 364 | table.docutils td, table.docutils th { 365 | padding: 1px 8px 1px 5px; 366 | border-top: 0; 367 | border-left: 0; 368 | border-right: 0; 369 | border-bottom: 1px solid #aaa; 370 | } 371 | 372 | table.footnote td, table.footnote th { 373 | border: 0 !important; 374 | } 375 | 376 | th { 377 | text-align: left; 378 | padding-right: 5px; 379 | } 380 | 381 | table.citation { 382 | border-left: solid 1px gray; 383 | margin-left: 1px; 384 | } 385 | 386 | table.citation td { 387 | border-bottom: none; 388 | } 389 | 390 | /* -- figures --------------------------------------------------------------- */ 391 | 392 | div.figure { 393 | margin: 0.5em; 394 | padding: 0.5em; 395 | } 396 | 397 | div.figure p.caption { 398 | padding: 0.3em; 399 | } 400 | 401 | div.figure p.caption span.caption-number { 402 | font-style: italic; 403 | } 404 | 405 | div.figure p.caption span.caption-text { 406 | } 407 | 408 | /* -- field list styles ----------------------------------------------------- */ 409 | 410 | table.field-list td, table.field-list th { 411 | border: 0 !important; 412 | } 413 | 414 | .field-list ul { 415 | margin: 0; 416 | padding-left: 1em; 417 | } 418 | 419 | .field-list p { 420 | margin: 0; 421 | } 422 | 423 | .field-name { 424 | -moz-hyphens: manual; 425 | -ms-hyphens: manual; 426 | -webkit-hyphens: manual; 427 | hyphens: manual; 428 | } 429 | 430 | /* -- other body styles ----------------------------------------------------- */ 431 | 432 | ol.arabic { 433 | list-style: decimal; 434 | } 435 | 436 | ol.loweralpha { 437 | list-style: lower-alpha; 438 | } 439 | 440 | ol.upperalpha { 441 | list-style: upper-alpha; 442 | } 443 | 444 | ol.lowerroman { 445 | list-style: lower-roman; 446 | } 447 | 448 | ol.upperroman { 449 | list-style: upper-roman; 450 | } 451 | 452 | dl { 453 | margin-bottom: 15px; 454 | } 455 | 456 | dd p { 457 | margin-top: 0px; 458 | } 459 | 460 | dd ul, dd table { 461 | margin-bottom: 10px; 462 | } 463 | 464 | dd { 465 | margin-top: 3px; 466 | margin-bottom: 10px; 467 | margin-left: 30px; 468 | } 469 | 470 | dt:target, span.highlighted { 471 | background-color: #fbe54e; 472 | } 473 | 474 | rect.highlighted { 475 | fill: #fbe54e; 476 | } 477 | 478 | dl.glossary dt { 479 | font-weight: bold; 480 | font-size: 1.1em; 481 | } 482 | 483 | .optional { 484 | font-size: 1.3em; 485 | } 486 | 487 | .sig-paren { 488 | font-size: larger; 489 | } 490 | 491 | .versionmodified { 492 | font-style: italic; 493 | } 494 | 495 | .system-message { 496 | background-color: #fda; 497 | padding: 5px; 498 | border: 3px solid red; 499 | } 500 | 501 | .footnote:target { 502 | background-color: #ffa; 503 | } 504 | 505 | .line-block { 506 | display: block; 507 | margin-top: 1em; 508 | margin-bottom: 1em; 509 | } 510 | 511 | .line-block .line-block { 512 | margin-top: 0; 513 | margin-bottom: 0; 514 | margin-left: 1.5em; 515 | } 516 | 517 | .guilabel, .menuselection { 518 | font-family: sans-serif; 519 | } 520 | 521 | .accelerator { 522 | text-decoration: underline; 523 | } 524 | 525 | .classifier { 526 | font-style: oblique; 527 | } 528 | 529 | abbr, acronym { 530 | border-bottom: dotted 1px; 531 | cursor: help; 532 | } 533 | 534 | /* -- code displays --------------------------------------------------------- */ 535 | 536 | pre { 537 | overflow: auto; 538 | overflow-y: hidden; /* fixes display issues on Chrome browsers */ 539 | } 540 | 541 | span.pre { 542 | -moz-hyphens: none; 543 | -ms-hyphens: none; 544 | -webkit-hyphens: none; 545 | hyphens: none; 546 | } 547 | 548 | td.linenos pre { 549 | padding: 5px 0px; 550 | border: 0; 551 | background-color: transparent; 552 | color: #aaa; 553 | } 554 | 555 | table.highlighttable { 556 | margin-left: 0.5em; 557 | } 558 | 559 | table.highlighttable td { 560 | padding: 0 0.5em 0 0.5em; 561 | } 562 | 563 | div.code-block-caption { 564 | padding: 2px 5px; 565 | font-size: small; 566 | } 567 | 568 | div.code-block-caption code { 569 | background-color: transparent; 570 | } 571 | 572 | div.code-block-caption + div > div.highlight > pre { 573 | margin-top: 0; 574 | } 575 | 576 | div.code-block-caption span.caption-number { 577 | padding: 0.1em 0.3em; 578 | font-style: italic; 579 | } 580 | 581 | div.code-block-caption span.caption-text { 582 | } 583 | 584 | div.literal-block-wrapper { 585 | padding: 1em 1em 0; 586 | } 587 | 588 | div.literal-block-wrapper div.highlight { 589 | margin: 0; 590 | } 591 | 592 | code.descname { 593 | background-color: transparent; 594 | font-weight: bold; 595 | font-size: 1.2em; 596 | } 597 | 598 | code.descclassname { 599 | background-color: transparent; 600 | } 601 | 602 | code.xref, a code { 603 | background-color: transparent; 604 | font-weight: bold; 605 | } 606 | 607 | h1 code, h2 code, h3 code, h4 code, h5 code, h6 code { 608 | background-color: transparent; 609 | } 610 | 611 | .viewcode-link { 612 | float: right; 613 | } 614 | 615 | .viewcode-back { 616 | float: right; 617 | font-family: sans-serif; 618 | } 619 | 620 | div.viewcode-block:target { 621 | margin: -1px -10px; 622 | padding: 0 10px; 623 | } 624 | 625 | /* -- math display ---------------------------------------------------------- */ 626 | 627 | img.math { 628 | vertical-align: middle; 629 | } 630 | 631 | div.body div.math p { 632 | text-align: center; 633 | } 634 | 635 | span.eqno { 636 | float: right; 637 | } 638 | 639 | span.eqno a.headerlink { 640 | position: relative; 641 | left: 0px; 642 | z-index: 1; 643 | } 644 | 645 | div.math:hover a.headerlink { 646 | visibility: visible; 647 | } 648 | 649 | /* -- printout stylesheet --------------------------------------------------- */ 650 | 651 | @media print { 652 | div.document, 653 | div.documentwrapper, 654 | div.bodywrapper { 655 | margin: 0 !important; 656 | width: 100%; 657 | } 658 | 659 | div.sphinxsidebar, 660 | div.related, 661 | div.footer, 662 | #top-link { 663 | display: none; 664 | } 665 | } -------------------------------------------------------------------------------- /docs/_static/classic.css: -------------------------------------------------------------------------------- 1 | /* 2 | * classic.css_t 3 | * ~~~~~~~~~~~~~ 4 | * 5 | * Sphinx stylesheet -- classic theme. 6 | * 7 | * :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. 8 | * :license: BSD, see LICENSE for details. 9 | * 10 | */ 11 | 12 | @import url("basic.css"); 13 | 14 | /* -- page layout ----------------------------------------------------------- */ 15 | 16 | body { 17 | font-family: sans-serif; 18 | font-size: 100%; 19 | background-color: #11303d; 20 | color: #000; 21 | margin: 0; 22 | padding: 0; 23 | } 24 | 25 | div.document { 26 | background-color: #1c4e63; 27 | } 28 | 29 | div.documentwrapper { 30 | float: left; 31 | width: 100%; 32 | } 33 | 34 | div.bodywrapper { 35 | margin: 0 0 0 230px; 36 | } 37 | 38 | div.body { 39 | background-color: #ffffff; 40 | color: #000000; 41 | padding: 0 20px 30px 20px; 42 | } 43 | 44 | div.footer { 45 | color: #ffffff; 46 | width: 100%; 47 | padding: 9px 0 9px 0; 48 | text-align: center; 49 | font-size: 75%; 50 | } 51 | 52 | div.footer a { 53 | color: #ffffff; 54 | text-decoration: underline; 55 | } 56 | 57 | div.related { 58 | background-color: #133f52; 59 | line-height: 30px; 60 | color: #ffffff; 61 | } 62 | 63 | div.related a { 64 | color: #ffffff; 65 | } 66 | 67 | div.sphinxsidebar { 68 | } 69 | 70 | div.sphinxsidebar h3 { 71 | font-family: 'Trebuchet MS', sans-serif; 72 | color: #ffffff; 73 | font-size: 1.4em; 74 | font-weight: normal; 75 | margin: 0; 76 | padding: 0; 77 | } 78 | 79 | div.sphinxsidebar h3 a { 80 | color: #ffffff; 81 | } 82 | 83 | div.sphinxsidebar h4 { 84 | font-family: 'Trebuchet MS', sans-serif; 85 | color: #ffffff; 86 | font-size: 1.3em; 87 | font-weight: normal; 88 | margin: 5px 0 0 0; 89 | padding: 0; 90 | } 91 | 92 | div.sphinxsidebar p { 93 | color: #ffffff; 94 | } 95 | 96 | div.sphinxsidebar p.topless { 97 | margin: 5px 10px 10px 10px; 98 | } 99 | 100 | div.sphinxsidebar ul { 101 | margin: 10px; 102 | padding: 0; 103 | color: #ffffff; 104 | } 105 | 106 | div.sphinxsidebar a { 107 | color: #98dbcc; 108 | } 109 | 110 | div.sphinxsidebar input { 111 | border: 1px solid #98dbcc; 112 | font-family: sans-serif; 113 | font-size: 1em; 114 | } 115 | 116 | 117 | 118 | /* -- hyperlink styles ------------------------------------------------------ */ 119 | 120 | a { 121 | color: #355f7c; 122 | text-decoration: none; 123 | } 124 | 125 | a:visited { 126 | color: #355f7c; 127 | text-decoration: none; 128 | } 129 | 130 | a:hover { 131 | text-decoration: underline; 132 | } 133 | 134 | 135 | 136 | /* -- body styles ----------------------------------------------------------- */ 137 | 138 | div.body h1, 139 | div.body h2, 140 | div.body h3, 141 | div.body h4, 142 | div.body h5, 143 | div.body h6 { 144 | font-family: 'Trebuchet MS', sans-serif; 145 | background-color: #f2f2f2; 146 | font-weight: normal; 147 | color: #20435c; 148 | border-bottom: 1px solid #ccc; 149 | margin: 20px -20px 10px -20px; 150 | padding: 3px 0 3px 10px; 151 | } 152 | 153 | div.body h1 { margin-top: 0; font-size: 200%; } 154 | div.body h2 { font-size: 160%; } 155 | div.body h3 { font-size: 140%; } 156 | div.body h4 { font-size: 120%; } 157 | div.body h5 { font-size: 110%; } 158 | div.body h6 { font-size: 100%; } 159 | 160 | a.headerlink { 161 | color: #c60f0f; 162 | font-size: 0.8em; 163 | padding: 0 4px 0 4px; 164 | text-decoration: none; 165 | } 166 | 167 | a.headerlink:hover { 168 | background-color: #c60f0f; 169 | color: white; 170 | } 171 | 172 | div.body p, div.body dd, div.body li, div.body blockquote { 173 | text-align: justify; 174 | line-height: 130%; 175 | } 176 | 177 | div.admonition p.admonition-title + p { 178 | display: inline; 179 | } 180 | 181 | div.admonition p { 182 | margin-bottom: 5px; 183 | } 184 | 185 | div.admonition pre { 186 | margin-bottom: 5px; 187 | } 188 | 189 | div.admonition ul, div.admonition ol { 190 | margin-bottom: 5px; 191 | } 192 | 193 | div.note { 194 | background-color: #eee; 195 | border: 1px solid #ccc; 196 | } 197 | 198 | div.seealso { 199 | background-color: #ffc; 200 | border: 1px solid #ff6; 201 | } 202 | 203 | div.topic { 204 | background-color: #eee; 205 | } 206 | 207 | div.warning { 208 | background-color: #ffe4e4; 209 | border: 1px solid #f66; 210 | } 211 | 212 | p.admonition-title { 213 | display: inline; 214 | } 215 | 216 | p.admonition-title:after { 217 | content: ":"; 218 | } 219 | 220 | pre { 221 | padding: 5px; 222 | background-color: #eeffcc; 223 | color: #333333; 224 | line-height: 120%; 225 | border: 1px solid #ac9; 226 | border-left: none; 227 | border-right: none; 228 | } 229 | 230 | code { 231 | background-color: #ecf0f3; 232 | padding: 0 1px 0 1px; 233 | font-size: 0.95em; 234 | } 235 | 236 | th { 237 | background-color: #ede; 238 | } 239 | 240 | .warning code { 241 | background: #efc2c2; 242 | } 243 | 244 | .note code { 245 | background: #d6d6d6; 246 | } 247 | 248 | .viewcode-back { 249 | font-family: sans-serif; 250 | } 251 | 252 | div.viewcode-block:target { 253 | background-color: #f4debf; 254 | border-top: 1px solid #ac9; 255 | border-bottom: 1px solid #ac9; 256 | } 257 | 258 | div.code-block-caption { 259 | color: #efefef; 260 | background-color: #1c4e63; 261 | } -------------------------------------------------------------------------------- /docs/_static/comment-bright.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DOI-BLM/requests-arcgis-auth/e01c7b708638562efebb67b54a1f8a3bbcd1eff0/docs/_static/comment-bright.png -------------------------------------------------------------------------------- /docs/_static/comment-close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DOI-BLM/requests-arcgis-auth/e01c7b708638562efebb67b54a1f8a3bbcd1eff0/docs/_static/comment-close.png -------------------------------------------------------------------------------- /docs/_static/comment.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DOI-BLM/requests-arcgis-auth/e01c7b708638562efebb67b54a1f8a3bbcd1eff0/docs/_static/comment.png -------------------------------------------------------------------------------- /docs/_static/custom.css: -------------------------------------------------------------------------------- 1 | /* This file intentionally left blank. */ 2 | -------------------------------------------------------------------------------- /docs/_static/doctools.js: -------------------------------------------------------------------------------- 1 | /* 2 | * doctools.js 3 | * ~~~~~~~~~~~ 4 | * 5 | * Sphinx JavaScript utilities for all documentation. 6 | * 7 | * :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. 8 | * :license: BSD, see LICENSE for details. 9 | * 10 | */ 11 | 12 | /** 13 | * select a different prefix for underscore 14 | */ 15 | $u = _.noConflict(); 16 | 17 | /** 18 | * make the code below compatible with browsers without 19 | * an installed firebug like debugger 20 | if (!window.console || !console.firebug) { 21 | var names = ["log", "debug", "info", "warn", "error", "assert", "dir", 22 | "dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace", 23 | "profile", "profileEnd"]; 24 | window.console = {}; 25 | for (var i = 0; i < names.length; ++i) 26 | window.console[names[i]] = function() {}; 27 | } 28 | */ 29 | 30 | /** 31 | * small helper function to urldecode strings 32 | */ 33 | jQuery.urldecode = function(x) { 34 | return decodeURIComponent(x).replace(/\+/g, ' '); 35 | }; 36 | 37 | /** 38 | * small helper function to urlencode strings 39 | */ 40 | jQuery.urlencode = encodeURIComponent; 41 | 42 | /** 43 | * This function returns the parsed url parameters of the 44 | * current request. Multiple values per key are supported, 45 | * it will always return arrays of strings for the value parts. 46 | */ 47 | jQuery.getQueryParameters = function(s) { 48 | if (typeof s === 'undefined') 49 | s = document.location.search; 50 | var parts = s.substr(s.indexOf('?') + 1).split('&'); 51 | var result = {}; 52 | for (var i = 0; i < parts.length; i++) { 53 | var tmp = parts[i].split('=', 2); 54 | var key = jQuery.urldecode(tmp[0]); 55 | var value = jQuery.urldecode(tmp[1]); 56 | if (key in result) 57 | result[key].push(value); 58 | else 59 | result[key] = [value]; 60 | } 61 | return result; 62 | }; 63 | 64 | /** 65 | * highlight a given string on a jquery object by wrapping it in 66 | * span elements with the given class name. 67 | */ 68 | jQuery.fn.highlightText = function(text, className) { 69 | function highlight(node, addItems) { 70 | if (node.nodeType === 3) { 71 | var val = node.nodeValue; 72 | var pos = val.toLowerCase().indexOf(text); 73 | if (pos >= 0 && !jQuery(node.parentNode).hasClass(className)) { 74 | var span; 75 | var isInSVG = jQuery(node).closest("body, svg, foreignObject").is("svg"); 76 | if (isInSVG) { 77 | span = document.createElementNS("http://www.w3.org/2000/svg", "tspan"); 78 | } else { 79 | span = document.createElement("span"); 80 | span.className = className; 81 | } 82 | span.appendChild(document.createTextNode(val.substr(pos, text.length))); 83 | node.parentNode.insertBefore(span, node.parentNode.insertBefore( 84 | document.createTextNode(val.substr(pos + text.length)), 85 | node.nextSibling)); 86 | node.nodeValue = val.substr(0, pos); 87 | if (isInSVG) { 88 | var bbox = span.getBBox(); 89 | var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect"); 90 | rect.x.baseVal.value = bbox.x; 91 | rect.y.baseVal.value = bbox.y; 92 | rect.width.baseVal.value = bbox.width; 93 | rect.height.baseVal.value = bbox.height; 94 | rect.setAttribute('class', className); 95 | var parentOfText = node.parentNode.parentNode; 96 | addItems.push({ 97 | "parent": node.parentNode, 98 | "target": rect}); 99 | } 100 | } 101 | } 102 | else if (!jQuery(node).is("button, select, textarea")) { 103 | jQuery.each(node.childNodes, function() { 104 | highlight(this, addItems); 105 | }); 106 | } 107 | } 108 | var addItems = []; 109 | var result = this.each(function() { 110 | highlight(this, addItems); 111 | }); 112 | for (var i = 0; i < addItems.length; ++i) { 113 | jQuery(addItems[i].parent).before(addItems[i].target); 114 | } 115 | return result; 116 | }; 117 | 118 | /* 119 | * backward compatibility for jQuery.browser 120 | * This will be supported until firefox bug is fixed. 121 | */ 122 | if (!jQuery.browser) { 123 | jQuery.uaMatch = function(ua) { 124 | ua = ua.toLowerCase(); 125 | 126 | var match = /(chrome)[ \/]([\w.]+)/.exec(ua) || 127 | /(webkit)[ \/]([\w.]+)/.exec(ua) || 128 | /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || 129 | /(msie) ([\w.]+)/.exec(ua) || 130 | ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || 131 | []; 132 | 133 | return { 134 | browser: match[ 1 ] || "", 135 | version: match[ 2 ] || "0" 136 | }; 137 | }; 138 | jQuery.browser = {}; 139 | jQuery.browser[jQuery.uaMatch(navigator.userAgent).browser] = true; 140 | } 141 | 142 | /** 143 | * Small JavaScript module for the documentation. 144 | */ 145 | var Documentation = { 146 | 147 | init : function() { 148 | this.fixFirefoxAnchorBug(); 149 | this.highlightSearchWords(); 150 | this.initIndexTable(); 151 | 152 | }, 153 | 154 | /** 155 | * i18n support 156 | */ 157 | TRANSLATIONS : {}, 158 | PLURAL_EXPR : function(n) { return n === 1 ? 0 : 1; }, 159 | LOCALE : 'unknown', 160 | 161 | // gettext and ngettext don't access this so that the functions 162 | // can safely bound to a different name (_ = Documentation.gettext) 163 | gettext : function(string) { 164 | var translated = Documentation.TRANSLATIONS[string]; 165 | if (typeof translated === 'undefined') 166 | return string; 167 | return (typeof translated === 'string') ? translated : translated[0]; 168 | }, 169 | 170 | ngettext : function(singular, plural, n) { 171 | var translated = Documentation.TRANSLATIONS[singular]; 172 | if (typeof translated === 'undefined') 173 | return (n == 1) ? singular : plural; 174 | return translated[Documentation.PLURALEXPR(n)]; 175 | }, 176 | 177 | addTranslations : function(catalog) { 178 | for (var key in catalog.messages) 179 | this.TRANSLATIONS[key] = catalog.messages[key]; 180 | this.PLURAL_EXPR = new Function('n', 'return +(' + catalog.plural_expr + ')'); 181 | this.LOCALE = catalog.locale; 182 | }, 183 | 184 | /** 185 | * add context elements like header anchor links 186 | */ 187 | addContextElements : function() { 188 | $('div[id] > :header:first').each(function() { 189 | $('\u00B6'). 190 | attr('href', '#' + this.id). 191 | attr('title', _('Permalink to this headline')). 192 | appendTo(this); 193 | }); 194 | $('dt[id]').each(function() { 195 | $('\u00B6'). 196 | attr('href', '#' + this.id). 197 | attr('title', _('Permalink to this definition')). 198 | appendTo(this); 199 | }); 200 | }, 201 | 202 | /** 203 | * workaround a firefox stupidity 204 | * see: https://bugzilla.mozilla.org/show_bug.cgi?id=645075 205 | */ 206 | fixFirefoxAnchorBug : function() { 207 | if (document.location.hash && $.browser.mozilla) 208 | window.setTimeout(function() { 209 | document.location.href += ''; 210 | }, 10); 211 | }, 212 | 213 | /** 214 | * highlight the search words provided in the url in the text 215 | */ 216 | highlightSearchWords : function() { 217 | var params = $.getQueryParameters(); 218 | var terms = (params.highlight) ? params.highlight[0].split(/\s+/) : []; 219 | if (terms.length) { 220 | var body = $('div.body'); 221 | if (!body.length) { 222 | body = $('body'); 223 | } 224 | window.setTimeout(function() { 225 | $.each(terms, function() { 226 | body.highlightText(this.toLowerCase(), 'highlighted'); 227 | }); 228 | }, 10); 229 | $('') 231 | .appendTo($('#searchbox')); 232 | } 233 | }, 234 | 235 | /** 236 | * init the domain index toggle buttons 237 | */ 238 | initIndexTable : function() { 239 | var togglers = $('img.toggler').click(function() { 240 | var src = $(this).attr('src'); 241 | var idnum = $(this).attr('id').substr(7); 242 | $('tr.cg-' + idnum).toggle(); 243 | if (src.substr(-9) === 'minus.png') 244 | $(this).attr('src', src.substr(0, src.length-9) + 'plus.png'); 245 | else 246 | $(this).attr('src', src.substr(0, src.length-8) + 'minus.png'); 247 | }).css('display', ''); 248 | if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) { 249 | togglers.click(); 250 | } 251 | }, 252 | 253 | /** 254 | * helper function to hide the search marks again 255 | */ 256 | hideSearchWords : function() { 257 | $('#searchbox .highlight-link').fadeOut(300); 258 | $('span.highlighted').removeClass('highlighted'); 259 | }, 260 | 261 | /** 262 | * make the url absolute 263 | */ 264 | makeURL : function(relativeURL) { 265 | return DOCUMENTATION_OPTIONS.URL_ROOT + '/' + relativeURL; 266 | }, 267 | 268 | /** 269 | * get the current relative url 270 | */ 271 | getCurrentURL : function() { 272 | var path = document.location.pathname; 273 | var parts = path.split(/\//); 274 | $.each(DOCUMENTATION_OPTIONS.URL_ROOT.split(/\//), function() { 275 | if (this === '..') 276 | parts.pop(); 277 | }); 278 | var url = parts.join('/'); 279 | return path.substring(url.lastIndexOf('/') + 1, path.length - 1); 280 | }, 281 | 282 | initOnKeyListeners: function() { 283 | $(document).keyup(function(event) { 284 | var activeElementType = document.activeElement.tagName; 285 | // don't navigate when in search box or textarea 286 | if (activeElementType !== 'TEXTAREA' && activeElementType !== 'INPUT' && activeElementType !== 'SELECT') { 287 | switch (event.keyCode) { 288 | case 37: // left 289 | var prevHref = $('link[rel="prev"]').prop('href'); 290 | if (prevHref) { 291 | window.location.href = prevHref; 292 | return false; 293 | } 294 | case 39: // right 295 | var nextHref = $('link[rel="next"]').prop('href'); 296 | if (nextHref) { 297 | window.location.href = nextHref; 298 | return false; 299 | } 300 | } 301 | } 302 | }); 303 | } 304 | }; 305 | 306 | // quick alias for translations 307 | _ = Documentation.gettext; 308 | 309 | $(document).ready(function() { 310 | Documentation.init(); 311 | }); -------------------------------------------------------------------------------- /docs/_static/documentation_options.js: -------------------------------------------------------------------------------- 1 | var DOCUMENTATION_OPTIONS = { 2 | URL_ROOT: '', 3 | VERSION: '1.0', 4 | LANGUAGE: 'None', 5 | COLLAPSE_INDEX: false, 6 | FILE_SUFFIX: '.html', 7 | HAS_SOURCE: true, 8 | SOURCELINK_SUFFIX: '.txt' 9 | }; -------------------------------------------------------------------------------- /docs/_static/down-pressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DOI-BLM/requests-arcgis-auth/e01c7b708638562efebb67b54a1f8a3bbcd1eff0/docs/_static/down-pressed.png -------------------------------------------------------------------------------- /docs/_static/down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DOI-BLM/requests-arcgis-auth/e01c7b708638562efebb67b54a1f8a3bbcd1eff0/docs/_static/down.png -------------------------------------------------------------------------------- /docs/_static/file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DOI-BLM/requests-arcgis-auth/e01c7b708638562efebb67b54a1f8a3bbcd1eff0/docs/_static/file.png -------------------------------------------------------------------------------- /docs/_static/minus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DOI-BLM/requests-arcgis-auth/e01c7b708638562efebb67b54a1f8a3bbcd1eff0/docs/_static/minus.png -------------------------------------------------------------------------------- /docs/_static/plus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DOI-BLM/requests-arcgis-auth/e01c7b708638562efebb67b54a1f8a3bbcd1eff0/docs/_static/plus.png -------------------------------------------------------------------------------- /docs/_static/pygments.css: -------------------------------------------------------------------------------- 1 | .highlight .hll { background-color: #ffffcc } 2 | .highlight { background: #eeffcc; } 3 | .highlight .c { color: #408090; font-style: italic } /* Comment */ 4 | .highlight .err { border: 1px solid #FF0000 } /* Error */ 5 | .highlight .k { color: #007020; font-weight: bold } /* Keyword */ 6 | .highlight .o { color: #666666 } /* Operator */ 7 | .highlight .ch { color: #408090; font-style: italic } /* Comment.Hashbang */ 8 | .highlight .cm { color: #408090; font-style: italic } /* Comment.Multiline */ 9 | .highlight .cp { color: #007020 } /* Comment.Preproc */ 10 | .highlight .cpf { color: #408090; font-style: italic } /* Comment.PreprocFile */ 11 | .highlight .c1 { color: #408090; font-style: italic } /* Comment.Single */ 12 | .highlight .cs { color: #408090; background-color: #fff0f0 } /* Comment.Special */ 13 | .highlight .gd { color: #A00000 } /* Generic.Deleted */ 14 | .highlight .ge { font-style: italic } /* Generic.Emph */ 15 | .highlight .gr { color: #FF0000 } /* Generic.Error */ 16 | .highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */ 17 | .highlight .gi { color: #00A000 } /* Generic.Inserted */ 18 | .highlight .go { color: #333333 } /* Generic.Output */ 19 | .highlight .gp { color: #c65d09; font-weight: bold } /* Generic.Prompt */ 20 | .highlight .gs { font-weight: bold } /* Generic.Strong */ 21 | .highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ 22 | .highlight .gt { color: #0044DD } /* Generic.Traceback */ 23 | .highlight .kc { color: #007020; font-weight: bold } /* Keyword.Constant */ 24 | .highlight .kd { color: #007020; font-weight: bold } /* Keyword.Declaration */ 25 | .highlight .kn { color: #007020; font-weight: bold } /* Keyword.Namespace */ 26 | .highlight .kp { color: #007020 } /* Keyword.Pseudo */ 27 | .highlight .kr { color: #007020; font-weight: bold } /* Keyword.Reserved */ 28 | .highlight .kt { color: #902000 } /* Keyword.Type */ 29 | .highlight .m { color: #208050 } /* Literal.Number */ 30 | .highlight .s { color: #4070a0 } /* Literal.String */ 31 | .highlight .na { color: #4070a0 } /* Name.Attribute */ 32 | .highlight .nb { color: #007020 } /* Name.Builtin */ 33 | .highlight .nc { color: #0e84b5; font-weight: bold } /* Name.Class */ 34 | .highlight .no { color: #60add5 } /* Name.Constant */ 35 | .highlight .nd { color: #555555; font-weight: bold } /* Name.Decorator */ 36 | .highlight .ni { color: #d55537; font-weight: bold } /* Name.Entity */ 37 | .highlight .ne { color: #007020 } /* Name.Exception */ 38 | .highlight .nf { color: #06287e } /* Name.Function */ 39 | .highlight .nl { color: #002070; font-weight: bold } /* Name.Label */ 40 | .highlight .nn { color: #0e84b5; font-weight: bold } /* Name.Namespace */ 41 | .highlight .nt { color: #062873; font-weight: bold } /* Name.Tag */ 42 | .highlight .nv { color: #bb60d5 } /* Name.Variable */ 43 | .highlight .ow { color: #007020; font-weight: bold } /* Operator.Word */ 44 | .highlight .w { color: #bbbbbb } /* Text.Whitespace */ 45 | .highlight .mb { color: #208050 } /* Literal.Number.Bin */ 46 | .highlight .mf { color: #208050 } /* Literal.Number.Float */ 47 | .highlight .mh { color: #208050 } /* Literal.Number.Hex */ 48 | .highlight .mi { color: #208050 } /* Literal.Number.Integer */ 49 | .highlight .mo { color: #208050 } /* Literal.Number.Oct */ 50 | .highlight .sa { color: #4070a0 } /* Literal.String.Affix */ 51 | .highlight .sb { color: #4070a0 } /* Literal.String.Backtick */ 52 | .highlight .sc { color: #4070a0 } /* Literal.String.Char */ 53 | .highlight .dl { color: #4070a0 } /* Literal.String.Delimiter */ 54 | .highlight .sd { color: #4070a0; font-style: italic } /* Literal.String.Doc */ 55 | .highlight .s2 { color: #4070a0 } /* Literal.String.Double */ 56 | .highlight .se { color: #4070a0; font-weight: bold } /* Literal.String.Escape */ 57 | .highlight .sh { color: #4070a0 } /* Literal.String.Heredoc */ 58 | .highlight .si { color: #70a0d0; font-style: italic } /* Literal.String.Interpol */ 59 | .highlight .sx { color: #c65d09 } /* Literal.String.Other */ 60 | .highlight .sr { color: #235388 } /* Literal.String.Regex */ 61 | .highlight .s1 { color: #4070a0 } /* Literal.String.Single */ 62 | .highlight .ss { color: #517918 } /* Literal.String.Symbol */ 63 | .highlight .bp { color: #007020 } /* Name.Builtin.Pseudo */ 64 | .highlight .fm { color: #06287e } /* Name.Function.Magic */ 65 | .highlight .vc { color: #bb60d5 } /* Name.Variable.Class */ 66 | .highlight .vg { color: #bb60d5 } /* Name.Variable.Global */ 67 | .highlight .vi { color: #bb60d5 } /* Name.Variable.Instance */ 68 | .highlight .vm { color: #bb60d5 } /* Name.Variable.Magic */ 69 | .highlight .il { color: #208050 } /* Literal.Number.Integer.Long */ -------------------------------------------------------------------------------- /docs/_static/sidebar.js: -------------------------------------------------------------------------------- 1 | /* 2 | * sidebar.js 3 | * ~~~~~~~~~~ 4 | * 5 | * This script makes the Sphinx sidebar collapsible. 6 | * 7 | * .sphinxsidebar contains .sphinxsidebarwrapper. This script adds 8 | * in .sphixsidebar, after .sphinxsidebarwrapper, the #sidebarbutton 9 | * used to collapse and expand the sidebar. 10 | * 11 | * When the sidebar is collapsed the .sphinxsidebarwrapper is hidden 12 | * and the width of the sidebar and the margin-left of the document 13 | * are decreased. When the sidebar is expanded the opposite happens. 14 | * This script saves a per-browser/per-session cookie used to 15 | * remember the position of the sidebar among the pages. 16 | * Once the browser is closed the cookie is deleted and the position 17 | * reset to the default (expanded). 18 | * 19 | * :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. 20 | * :license: BSD, see LICENSE for details. 21 | * 22 | */ 23 | 24 | $(function() { 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | // global elements used by the functions. 34 | // the 'sidebarbutton' element is defined as global after its 35 | // creation, in the add_sidebar_button function 36 | var bodywrapper = $('.bodywrapper'); 37 | var sidebar = $('.sphinxsidebar'); 38 | var sidebarwrapper = $('.sphinxsidebarwrapper'); 39 | 40 | // for some reason, the document has no sidebar; do not run into errors 41 | if (!sidebar.length) return; 42 | 43 | // original margin-left of the bodywrapper and width of the sidebar 44 | // with the sidebar expanded 45 | var bw_margin_expanded = bodywrapper.css('margin-left'); 46 | var ssb_width_expanded = sidebar.width(); 47 | 48 | // margin-left of the bodywrapper and width of the sidebar 49 | // with the sidebar collapsed 50 | var bw_margin_collapsed = '.8em'; 51 | var ssb_width_collapsed = '.8em'; 52 | 53 | // colors used by the current theme 54 | var dark_color = $('.related').css('background-color'); 55 | var light_color = $('.document').css('background-color'); 56 | 57 | function sidebar_is_collapsed() { 58 | return sidebarwrapper.is(':not(:visible)'); 59 | } 60 | 61 | function toggle_sidebar() { 62 | if (sidebar_is_collapsed()) 63 | expand_sidebar(); 64 | else 65 | collapse_sidebar(); 66 | } 67 | 68 | function collapse_sidebar() { 69 | sidebarwrapper.hide(); 70 | sidebar.css('width', ssb_width_collapsed); 71 | bodywrapper.css('margin-left', bw_margin_collapsed); 72 | sidebarbutton.css({ 73 | 'margin-left': '0', 74 | 'height': bodywrapper.height() 75 | }); 76 | sidebarbutton.find('span').text('»'); 77 | sidebarbutton.attr('title', _('Expand sidebar')); 78 | document.cookie = 'sidebar=collapsed'; 79 | } 80 | 81 | function expand_sidebar() { 82 | bodywrapper.css('margin-left', bw_margin_expanded); 83 | sidebar.css('width', ssb_width_expanded); 84 | sidebarwrapper.show(); 85 | sidebarbutton.css({ 86 | 'margin-left': ssb_width_expanded-12, 87 | 'height': bodywrapper.height() 88 | }); 89 | sidebarbutton.find('span').text('«'); 90 | sidebarbutton.attr('title', _('Collapse sidebar')); 91 | document.cookie = 'sidebar=expanded'; 92 | } 93 | 94 | function add_sidebar_button() { 95 | sidebarwrapper.css({ 96 | 'float': 'left', 97 | 'margin-right': '0', 98 | 'width': ssb_width_expanded - 28 99 | }); 100 | // create the button 101 | sidebar.append( 102 | '
«
' 103 | ); 104 | var sidebarbutton = $('#sidebarbutton'); 105 | light_color = sidebarbutton.css('background-color'); 106 | // find the height of the viewport to center the '<<' in the page 107 | var viewport_height; 108 | if (window.innerHeight) 109 | viewport_height = window.innerHeight; 110 | else 111 | viewport_height = $(window).height(); 112 | sidebarbutton.find('span').css({ 113 | 'display': 'block', 114 | 'margin-top': (viewport_height - sidebar.position().top - 20) / 2 115 | }); 116 | 117 | sidebarbutton.click(toggle_sidebar); 118 | sidebarbutton.attr('title', _('Collapse sidebar')); 119 | sidebarbutton.css({ 120 | 'color': '#FFFFFF', 121 | 'border-left': '1px solid ' + dark_color, 122 | 'font-size': '1.2em', 123 | 'cursor': 'pointer', 124 | 'height': bodywrapper.height(), 125 | 'padding-top': '1px', 126 | 'margin-left': ssb_width_expanded - 12 127 | }); 128 | 129 | sidebarbutton.hover( 130 | function () { 131 | $(this).css('background-color', dark_color); 132 | }, 133 | function () { 134 | $(this).css('background-color', light_color); 135 | } 136 | ); 137 | } 138 | 139 | function set_position_from_cookie() { 140 | if (!document.cookie) 141 | return; 142 | var items = document.cookie.split(';'); 143 | for(var k=0; k2;a== 12 | null&&(a=[]);if(y&&a.reduce===y)return e&&(c=b.bind(c,e)),f?a.reduce(c,d):a.reduce(c);j(a,function(a,b,i){f?d=c.call(e,d,a,b,i):(d=a,f=true)});if(!f)throw new TypeError("Reduce of empty array with no initial value");return d};b.reduceRight=b.foldr=function(a,c,d,e){var f=arguments.length>2;a==null&&(a=[]);if(z&&a.reduceRight===z)return e&&(c=b.bind(c,e)),f?a.reduceRight(c,d):a.reduceRight(c);var g=b.toArray(a).reverse();e&&!f&&(c=b.bind(c,e));return f?b.reduce(g,c,d,e):b.reduce(g,c)};b.find=b.detect= 13 | function(a,c,b){var e;E(a,function(a,g,h){if(c.call(b,a,g,h))return e=a,true});return e};b.filter=b.select=function(a,c,b){var e=[];if(a==null)return e;if(A&&a.filter===A)return a.filter(c,b);j(a,function(a,g,h){c.call(b,a,g,h)&&(e[e.length]=a)});return e};b.reject=function(a,c,b){var e=[];if(a==null)return e;j(a,function(a,g,h){c.call(b,a,g,h)||(e[e.length]=a)});return e};b.every=b.all=function(a,c,b){var e=true;if(a==null)return e;if(B&&a.every===B)return a.every(c,b);j(a,function(a,g,h){if(!(e= 14 | e&&c.call(b,a,g,h)))return n});return e};var E=b.some=b.any=function(a,c,d){c||(c=b.identity);var e=false;if(a==null)return e;if(C&&a.some===C)return a.some(c,d);j(a,function(a,b,h){if(e||(e=c.call(d,a,b,h)))return n});return!!e};b.include=b.contains=function(a,c){var b=false;if(a==null)return b;return p&&a.indexOf===p?a.indexOf(c)!=-1:b=E(a,function(a){return a===c})};b.invoke=function(a,c){var d=i.call(arguments,2);return b.map(a,function(a){return(b.isFunction(c)?c||a:a[c]).apply(a,d)})};b.pluck= 15 | function(a,c){return b.map(a,function(a){return a[c]})};b.max=function(a,c,d){if(!c&&b.isArray(a))return Math.max.apply(Math,a);if(!c&&b.isEmpty(a))return-Infinity;var e={computed:-Infinity};j(a,function(a,b,h){b=c?c.call(d,a,b,h):a;b>=e.computed&&(e={value:a,computed:b})});return e.value};b.min=function(a,c,d){if(!c&&b.isArray(a))return Math.min.apply(Math,a);if(!c&&b.isEmpty(a))return Infinity;var e={computed:Infinity};j(a,function(a,b,h){b=c?c.call(d,a,b,h):a;bd?1:0}),"value")};b.groupBy=function(a,c){var d={},e=b.isFunction(c)?c:function(a){return a[c]};j(a,function(a,b){var c=e(a,b);(d[c]||(d[c]=[])).push(a)});return d};b.sortedIndex=function(a, 17 | c,d){d||(d=b.identity);for(var e=0,f=a.length;e>1;d(a[g])=0})})};b.difference=function(a){var c=b.flatten(i.call(arguments,1));return b.filter(a,function(a){return!b.include(c,a)})};b.zip=function(){for(var a=i.call(arguments),c=b.max(b.pluck(a,"length")),d=Array(c),e=0;e=0;d--)b=[a[d].apply(this,b)];return b[0]}}; 24 | b.after=function(a,b){return a<=0?b():function(){if(--a<1)return b.apply(this,arguments)}};b.keys=J||function(a){if(a!==Object(a))throw new TypeError("Invalid object");var c=[],d;for(d in a)b.has(a,d)&&(c[c.length]=d);return c};b.values=function(a){return b.map(a,b.identity)};b.functions=b.methods=function(a){var c=[],d;for(d in a)b.isFunction(a[d])&&c.push(d);return c.sort()};b.extend=function(a){j(i.call(arguments,1),function(b){for(var d in b)a[d]=b[d]});return a};b.defaults=function(a){j(i.call(arguments, 25 | 1),function(b){for(var d in b)a[d]==null&&(a[d]=b[d])});return a};b.clone=function(a){return!b.isObject(a)?a:b.isArray(a)?a.slice():b.extend({},a)};b.tap=function(a,b){b(a);return a};b.isEqual=function(a,b){return q(a,b,[])};b.isEmpty=function(a){if(b.isArray(a)||b.isString(a))return a.length===0;for(var c in a)if(b.has(a,c))return false;return true};b.isElement=function(a){return!!(a&&a.nodeType==1)};b.isArray=o||function(a){return l.call(a)=="[object Array]"};b.isObject=function(a){return a===Object(a)}; 26 | b.isArguments=function(a){return l.call(a)=="[object Arguments]"};if(!b.isArguments(arguments))b.isArguments=function(a){return!(!a||!b.has(a,"callee"))};b.isFunction=function(a){return l.call(a)=="[object Function]"};b.isString=function(a){return l.call(a)=="[object String]"};b.isNumber=function(a){return l.call(a)=="[object Number]"};b.isNaN=function(a){return a!==a};b.isBoolean=function(a){return a===true||a===false||l.call(a)=="[object Boolean]"};b.isDate=function(a){return l.call(a)=="[object Date]"}; 27 | b.isRegExp=function(a){return l.call(a)=="[object RegExp]"};b.isNull=function(a){return a===null};b.isUndefined=function(a){return a===void 0};b.has=function(a,b){return I.call(a,b)};b.noConflict=function(){r._=G;return this};b.identity=function(a){return a};b.times=function(a,b,d){for(var e=0;e/g,">").replace(/"/g,""").replace(/'/g,"'").replace(/\//g,"/")};b.mixin=function(a){j(b.functions(a), 28 | function(c){K(c,b[c]=a[c])})};var L=0;b.uniqueId=function(a){var b=L++;return a?a+b:b};b.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var t=/.^/,u=function(a){return a.replace(/\\\\/g,"\\").replace(/\\'/g,"'")};b.template=function(a,c){var d=b.templateSettings,d="var __p=[],print=function(){__p.push.apply(__p,arguments);};with(obj||{}){__p.push('"+a.replace(/\\/g,"\\\\").replace(/'/g,"\\'").replace(d.escape||t,function(a,b){return"',_.escape("+ 29 | u(b)+"),'"}).replace(d.interpolate||t,function(a,b){return"',"+u(b)+",'"}).replace(d.evaluate||t,function(a,b){return"');"+u(b).replace(/[\r\n\t]/g," ")+";__p.push('"}).replace(/\r/g,"\\r").replace(/\n/g,"\\n").replace(/\t/g,"\\t")+"');}return __p.join('');",e=new Function("obj","_",d);return c?e(c,b):function(a){return e.call(this,a,b)}};b.chain=function(a){return b(a).chain()};var m=function(a){this._wrapped=a};b.prototype=m.prototype;var v=function(a,c){return c?b(a).chain():a},K=function(a,c){m.prototype[a]= 30 | function(){var a=i.call(arguments);H.call(a,this._wrapped);return v(c.apply(b,a),this._chain)}};b.mixin(b);j("pop,push,reverse,shift,sort,splice,unshift".split(","),function(a){var b=k[a];m.prototype[a]=function(){var d=this._wrapped;b.apply(d,arguments);var e=d.length;(a=="shift"||a=="splice")&&e===0&&delete d[0];return v(d,this._chain)}});j(["concat","join","slice"],function(a){var b=k[a];m.prototype[a]=function(){return v(b.apply(this._wrapped,arguments),this._chain)}});m.prototype.chain=function(){this._chain= 31 | true;return this};m.prototype.value=function(){return this._wrapped}}).call(this); 32 | -------------------------------------------------------------------------------- /docs/_static/up-pressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DOI-BLM/requests-arcgis-auth/e01c7b708638562efebb67b54a1f8a3bbcd1eff0/docs/_static/up-pressed.png -------------------------------------------------------------------------------- /docs/_static/up.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DOI-BLM/requests-arcgis-auth/e01c7b708638562efebb67b54a1f8a3bbcd1eff0/docs/_static/up.png -------------------------------------------------------------------------------- /docs/genindex.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 8 | 9 | 10 | Index — requests_arcgis_auth 1.0 documentation 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 29 | 30 |
31 |
32 |
33 |
34 | 35 | 36 |

Index

37 | 38 |
39 | A 40 | | R 41 | | T 42 | 43 |
44 |

A

45 | 46 | 52 | 58 |
59 | 60 |

R

61 | 62 | 66 |
67 | 68 |

T

69 | 70 | 74 | 78 |
79 | 80 | 81 | 82 |
83 |
84 |
85 | 101 |
102 |
103 | 112 | 116 | 117 | -------------------------------------------------------------------------------- /docs/objects.inv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DOI-BLM/requests-arcgis-auth/e01c7b708638562efebb67b54a1f8a3bbcd1eff0/docs/objects.inv -------------------------------------------------------------------------------- /docs/py-modindex.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | Python Module Index — requests_arcgis_auth 1.0 documentation 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 23 | 24 | 25 | 26 | 38 | 39 |
40 |
41 |
42 |
43 | 44 | 45 |

Python Module Index

46 | 47 |
48 | r 49 |
50 | 51 | 52 | 53 | 55 | 56 | 57 | 60 |
 
54 | r
58 | requests_arcgis_auth 59 |
61 | 62 | 63 |
64 |
65 |
66 | 82 |
83 |
84 | 96 | 100 | 101 | -------------------------------------------------------------------------------- /docs/search.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | Search — requests_arcgis_auth 1.0 documentation 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 22 | 23 | 24 | 25 | 26 | 27 | 36 | 37 |
38 |
39 |
40 |
41 | 42 |

Search

43 |
44 | 45 |

46 | Please activate JavaScript to enable the search 47 | functionality. 48 |

49 |
50 |

51 | From here you can search these documents. Enter your search 52 | words into the box below and click "search". Note that the search 53 | function will automatically search for all of the words. Pages 54 | containing fewer words won't appear in the result list. 55 |

56 |
57 | 58 | 59 | 60 |
61 | 62 |
63 | 64 |
65 | 66 |
67 |
68 |
69 | 73 |
74 |
75 | 84 | 88 | 89 | -------------------------------------------------------------------------------- /docs/searchindex.js: -------------------------------------------------------------------------------- 1 | Search.setIndex({docnames:["index"],envversion:52,filenames:["index.rst"],objects:{"requests_arcgis_auth.ArcGISPortalSAMLAuth":{redirect_uri:[0,1,1,""]},requests_arcgis_auth:{ArcGISPortalSAMLAuth:[0,0,1,""],ArcGISPortalTokenAuth:[0,0,1,""],ArcGISServerAuth:[0,0,1,""],ArcGISServerTokenAuth:[0,0,1,""],TokenAuthenticationError:[0,2,1,""],TokenAuthenticationWarning:[0,2,1,""]}},objnames:{"0":["py","class","Python class"],"1":["py","attribute","Python attribute"],"2":["py","exception","Python exception"]},objtypes:{"0":"py:class","1":"py:attribute","2":"py:exception"},terms:{"02r30000009z000000":0,"02r3000000m5000000":0,"3rd":0,"class":0,"default":0,"import":0,"int":0,"true":0,For:[],Not:0,The:0,There:[],Use:0,about:0,acquir:0,adaptor:0,add:[],administ:0,advantag:0,again:0,agol:0,aliv:[],all:0,allow:0,alon:0,also:0,api:0,applic:0,approach:0,appropri:0,arcgi:0,arcgis_auth:[],arcgisportalauth:0,arcgisportalsamlauth:[],arcgisportaltokenauth:[],arcgisserverauth:[],arcgisservertokenauth:[],arg:0,assert:0,attempt:0,attribut:0,auth:0,authent:0,author:0,automat:[],back:0,base:0,beautifulsoup4:0,been:0,behold:[],blah:[],blm:[],bool:0,bundl:0,can:0,canon:[],captur:0,capture_request_histori:0,capture_requests_histori:0,caution:0,certif:0,charset:[],classindex:[],client:0,client_id:0,com:0,configur:0,connect:[],content:[],could:0,cover:[],credenti:0,current:[],custom:0,data:[],depart:0,depend:[],deploy:0,deriv:0,descript:[],desir:0,desktop:0,develop:0,dict:0,dictionari:0,differ:0,disabil:0,doc:0,doe:0,doi:0,domain:0,enabl:0,encod:[],enterpris:0,esri:0,event:0,exampl:0,expir:0,extern:[],fals:0,featur:0,fed:[],feder:0,fill:[],follow:0,form:0,format:0,found:0,from:0,further:0,furthermor:[],gener:0,generate_token:0,get:0,github:[],gov_blm_egi:[],grant:0,grass:[],handler:0,has:0,header:0,help:0,here:0,histori:0,htm:0,html:0,http:0,httpkerberosauth:0,ident:0,ietf:0,implement:0,index:0,inform:0,init:[],inspect:0,instal:0,instanc:0,integr:0,interior:0,json:0,keep:[],kerbero:0,kerberos_:0,known:0,kwarg:0,labor:[],languag:0,latest:0,leav:0,lever:0,leverag:0,librari:[],link:[],log:0,login:0,manual:[],map:0,markup:0,master:0,memori:0,microsoft:0,minut:0,model:0,modul:0,most:[],mutual:0,name:0,need:0,none:0,note:[],ntlm:0,oauth2:0,oauth:0,obj:0,object:0,onli:0,onlin:0,oob:0,option:0,org:0,organ:[],other:0,overview:[],own:0,page:0,paramet:0,part:[],parti:0,pass:[],password:0,pfopp:[],pool:[],portal:0,post:[],power:[],print:0,private_gist:[],product:0,proprietari:0,propriteri:0,provid:0,prowestgi:0,purpos:0,python:0,queri:[],reccomend:0,redirect:0,redirect_uri:0,refere:0,regist:0,request:0,requests_auth_handl:0,requests_kerbero:0,requests_ntlm:0,requir:0,resourc:0,respons:0,rest:0,right:[],saml:0,saml_auth:0,saml_head:0,sampl:[],san:[],scheme:0,search:0,secur:0,see:[],self:0,send:[],serevic:[],server:0,servic:0,session:0,setup:0,share:0,should:0,sign:0,similar:[],singl:0,site:0,solut:0,sourc:0,specifi:0,specific:0,ssl:0,stand:0,standard:0,statu:0,status_cod:[],store:0,str:0,string:[],suppli:0,support:0,test:0,text:[],thank:[],theoret:0,thi:0,tie:0,tier:0,token:0,tokenauthenticationerror:0,tokenauthenticationwarn:0,total_private_repo:[],type:[],underli:0,unless:0,uri:0,url:[],urllib3:[],urn:0,use:0,used:0,user:0,usernam:0,using:0,utf8:[],utf:[],vendor:0,verifi:0,via:0,web:0,were:0,where:[],window:0,without:[],work:0,workflow:0,write:0,www:0,you:0,your:[]},titles:["Welcome to requests_arcgis_auth\u2019s documentation!"],titleterms:{arcgisportalsamlauth:0,arcgisportaltokenauth:0,arcgisserverauth:0,arcgisservertokenauth:0,authent:[],code:0,develop:[],document:0,exampl:[],except:0,indic:0,interfac:[],kerbero:[],refer:0,requests_arcgis_auth:0,sampl:0,tabl:0,tier:[],web:[],welcom:0}}) -------------------------------------------------------------------------------- /requests_arcgis_auth/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | from .arcgis_token_auth import ArcGISServerTokenAuth, ArcGISPortalTokenAuth 3 | from .arcgis_auth import ArcGISServerAuth, ArcGISPortalAuth 4 | from .arcgis_saml_auth import ArcGISPortalSAMLAuth 5 | from .arcgis_exceptions import TokenAuthenticationError, TokenAuthenticationWarning 6 | 7 | __all__ = ('ArcGISServerTokenAuth', 8 | 'ArcGISServerAuth', 9 | 'ArcGISPortalTokenAuth', 10 | 'ArcGISPortalAuth', 11 | 'ArcGISPortalSAMLAuth', 12 | 'TokenAuthenticationError', 13 | 'TokenAuthenticationWarning') 14 | -------------------------------------------------------------------------------- /requests_arcgis_auth/arcgis_auth.py: -------------------------------------------------------------------------------- 1 | """ 2 | .. module:: arcgis_auth 3 | :platform: Windows 4 | :synopsis: Used for Authentication to an Esri ArcGIS Server or Portal. 5 | Supports web-tier security (Kerberos, NTLM) and Token Authentication 6 | """ 7 | 8 | import os 9 | from datetime import datetime 10 | import time 11 | import warnings 12 | import json 13 | import requests 14 | from requests.auth import AuthBase 15 | from requests_kerberos import HTTPKerberosAuth, OPTIONAL 16 | from requests_ntlm import HttpNtlmAuth 17 | from bs4 import BeautifulSoup 18 | import re 19 | 20 | from arcgis_token_auth import ArcGISServerTokenAuth, ArcGISPortalTokenAuth 21 | from arcgis_exceptions import TokenAuthenticationError, TokenAuthenticationWarning 22 | 23 | # Python v3 commpatability 24 | try: 25 | from urllib import urlencode 26 | from urlparse import urlparse 27 | except: 28 | from urllib.parse import urlparse 29 | def urlencode(input_dict): 30 | return ('&'.join(['{}={}'.format(quote(k, safe='/'), quote(v, safe='/')) 31 | for k, v in input_dict.items()])) 32 | 33 | 34 | 35 | # Added this to be able to execute from PyScripter (which kept throwing errors about not being in a 'package'). 36 | """try: 37 | from .arcgis_exceptions import TokenAuthenticationError, TokenAuthenticationWarning 38 | except: 39 | import sys 40 | from os import path 41 | sys.path.append( path.dirname( path.dirname( path.abspath(__file__) ) ) ) 42 | from arcgis_exceptions import TokenAuthenticationError, TokenAuthenticationWarning 43 | """ 44 | 45 | """ 46 | TODOS 47 | Try to securely pass it (with post in the body). Esri does not seem to support that on the admin interface. For now, just add to the URI parameters 48 | if username/pwd is wrong... dont keep re-requesting it... accounts get locked easily (3 failed login attempts)? 49 | """ 50 | 51 | """ NOTES 52 | will generate a token using the token URL from the FIRST REQUEST only at this point 53 | Meaning the token object will not be able to be re-used between management interfaces (seperate ArcGIS for Server Sites) 54 | """ 55 | 56 | 57 | class ArcGISServerAuth(ArcGISServerTokenAuth,HTTPKerberosAuth,HttpNtlmAuth): 58 | 59 | """Esri ArcGIS for Server (Stand Alone) authentication handler for the python requests API. 60 | supports the vendor proprietary 'Token Based' authentication and web-tier security using Kerberos or NTLM. 61 | 62 | Args: 63 | username (:obj:`str`, Optional): username of user authenticating. Only required for token authentication or NTLM 64 | password (:obj:`str`, Optional): password of user authenticating. Only required for token authentication or NTLM 65 | verify (:obj:`bool`, Optional): Verify SSL Certificates (default: True). Use caution disabiling this (not reccomended for production use) 66 | instance (:obj:`str`, Optional): The 'instance' name of the ArcGIS for Server Site (also known as the web-adaptor name). This will be derived if not supplied. ex: 'arcgis' 67 | """ 68 | 69 | def __init__(self,username=None,password=None,verify=True,instance=None): 70 | 71 | super(ArcGISServerAuth, self).__init__(username,password,verify,instance) 72 | self._instanceof=None 73 | 74 | def __call__(self,r): 75 | 76 | self._init(r) 77 | 78 | # Possible future TODO - what if there is no auth handler set??? For now, do not raise an exception... This would support 'anonymous' access. 79 | if self._instanceof is None: 80 | warnings.warn("Unable to authenticate with the site; site does not support token, kerberos, or NTLM authentication.",TokenAuthenticationWarning) 81 | return r 82 | 83 | return self._instanceof.__call__(self,r) 84 | 85 | def _init(self,r): 86 | # Only execute if after initialized (first request) 87 | 88 | # Derive Auth Information 89 | if self._auth_info is None: 90 | self._determine_auth_handler(r) 91 | 92 | def _determine_auth_handler(self,r): 93 | # Determine the Authenticaiton Handler to use (token, kerberos, NTLM) 94 | 95 | # First try the Token Authentication 96 | try: 97 | ArcGISServerTokenAuth._init(self,r) 98 | if self._auth_info.get("isTokenBasedSecurity"): 99 | self._instanceof=ArcGISServerTokenAuth 100 | return True 101 | except TokenAuthenticationError: 102 | # catch & throw away exception and try other handlers. 103 | pass 104 | 105 | # If token auth fails, check for "Web-Tier" security 106 | lr = self._last_request 107 | auths=[] 108 | if lr.status_code == 401 and lr.headers.get("WWW-Authenticate") is not None: 109 | auths=lr.headers.get("WWW-Authenticate").split(", ") 110 | 111 | # Try Kerberos 112 | if 'Negotiate' in auths: 113 | test_req = requests.head(r.url,auth=HTTPKerberosAuth(),verify=self.verify) 114 | if test_req.ok: 115 | self._instanceof = HTTPKerberosAuth 116 | self._auth_info={"isTokenBasedSecurity": False} 117 | HTTPKerberosAuth.__init__(self) 118 | return True 119 | 120 | # Try NTLM 121 | if 'Negotiate' in auths or 'NTLM' in auths: 122 | test_req = requests.head(r.url,auth=HttpNtlmAuth(self.username,self.password),verify=self.verify) 123 | if test_req.ok: 124 | self._instanceof = HttpNtlmAuth 125 | self._auth_info={"isTokenBasedSecurity": False} 126 | HttpNtlmAuth.__init__(self,self.username,self.password) 127 | return True 128 | 129 | return False 130 | 131 | 132 | def _derive_instance(self,r): 133 | 134 | # Need to determine the "instance" from the requesting URL, then security posture (info) endpoint. 135 | # Expected Inputs: 136 | # https://host/arcgis 137 | # https://host/arcgis/sharing 138 | # https://host/arcgis/sharing/rest 139 | # https://host:port/sharing/rest 140 | 141 | # Derive the 'Instance' (normally the first path element), unless it is "sharing" (ex: AGOL). This is the 'Web-Adaptor' name for on-premise portals 142 | if self.instance is None: 143 | up=urlparse(r.url) 144 | path1=up.path.split("/")[1] 145 | self.instance = path1 if path1 != "sharing" else "" 146 | 147 | class ArcGISPortalAuth(ArcGISPortalTokenAuth,HTTPKerberosAuth,HttpNtlmAuth): 148 | # Will determine security posture and will setup either web-tier or token security. 149 | 150 | """Python Requests Authentication Handler for the Esri Portal for ArcGIS product and ArcGIS Online. 151 | supports the vendor proprietary 'Token Based' authentication and web-tier security using Kerberos or NTLM. 152 | 153 | Args: 154 | username (:obj:`str`): Username of user authenticating. 155 | password (:obj:`str`): Password of user authenticating. 156 | verify (:obj:`bool`, Optional): Verify SSL Certificates (default: True). Use caution disabiling this (not reccomended for production use) 157 | instance (:obj:`str`, Optional): - The 'instance' name of the ArcGIS for Server Site (also known as the web-adaptor name). Code will attempt to derive if not supplied. ex: 'portal' 158 | """ 159 | 160 | def __init__(self,username=None,password=None,verify=True,instance=None): 161 | super(ArcGISPortalAuth, self).__init__(username,password,verify,instance) 162 | self._instanceof=None 163 | self._auth_info = None 164 | 165 | def __call__(self,r): 166 | 167 | self._init(r) 168 | 169 | # Possible future TODO - what if there is no auth handler set??? For now, do not raise an exception... This would support 'anonymous' access. 170 | if self._instanceof is None: 171 | warnings.warn("Unable to authenticate with the portal; portal does not support token, kerberos, or NTLM authentication.",TokenAuthenticationWarning) 172 | return r 173 | 174 | return self._instanceof.__call__(self,r) 175 | 176 | def _init(self,r): 177 | # Only execute if after initialized (first request) 178 | ArcGISPortalTokenAuth._init(self,r) 179 | 180 | # Derive Auth Information 181 | if self._auth_info is None: 182 | self._determine_auth_handler(r) 183 | 184 | def _set_token_auth_handler(self,r): 185 | ArcGISPortalTokenAuth._init(self,r) 186 | self._instanceof=ArcGISPortalTokenAuth 187 | self._auth_info={"isTokenBasedSecurity": True} 188 | return True 189 | 190 | def _determine_auth_handler(self,r): 191 | # Determine the Authenticaiton Handler to use (token, kerberos, NTLM) 192 | 193 | # First try the Token Authentication 194 | self._last_request=requests.head(self._get_token_url(r),verify=self.verify) 195 | if self._last_request.status_code==200: 196 | return self._set_token_auth_handler(r) 197 | 198 | # Had an issue that the HEAD method was not supported. Catch the 405 error code and try post. 199 | elif self._last_request.status_code == 405: 200 | self._last_request = requests.post(self._get_token_url(r),verify=self.verify) 201 | if self._last_request.status_code == 200: 202 | return self._set_token_auth_handler(r) 203 | 204 | # If token auth fails, check for "Web-Tier" security 205 | lr = self._last_request 206 | auths=[] 207 | if lr.status_code == 401 and lr.headers.get("WWW-Authenticate") is not None: 208 | auths=lr.headers.get("WWW-Authenticate").split(", ") 209 | 210 | # Try Kerberos 211 | if 'Negotiate' in auths: 212 | self._last_request = requests.head(r.url,auth=HTTPKerberosAuth(),verify=self.verify) 213 | if self._last_request.ok: 214 | self._instanceof = HTTPKerberosAuth 215 | self._auth_info={"isTokenBasedSecurity": False} 216 | HTTPKerberosAuth.__init__(self) 217 | return True 218 | 219 | # Try NTLM 220 | if 'Negotiate' in auths or 'NTLM' in auths: 221 | self._last_request = requests.head(r.url,auth=HttpNtlmAuth(self.username,self.password),verify=self.verify) 222 | if self._last_request.ok: 223 | self._instanceof = HttpNtlmAuth 224 | self._auth_info={"isTokenBasedSecurity": False} 225 | HttpNtlmAuth.__init__(self,self.username,self.password) 226 | return True 227 | 228 | return False 229 | 230 | 231 | 232 | 233 | 234 | -------------------------------------------------------------------------------- /requests_arcgis_auth/arcgis_exceptions.py: -------------------------------------------------------------------------------- 1 | from requests.exceptions import RequestException,RequestsWarning 2 | 3 | class TokenAuthenticationError(RequestException): 4 | """Site Does Not Support Token Authentication""" 5 | pass 6 | 7 | class TokenAuthenticationWarning(RequestsWarning): 8 | """Site Does Not Support Token Authentication""" 9 | pass 10 | -------------------------------------------------------------------------------- /requests_arcgis_auth/arcgis_token_auth.py: -------------------------------------------------------------------------------- 1 | """ 2 | .. module:: arcgis_token_auth 3 | :platform: Windows 4 | :synopsis: Used for Authentication to an Esri ArcGIS Server or Portal. 5 | Only Supports Token Authentication 6 | """ 7 | 8 | import os 9 | from datetime import datetime 10 | import time 11 | import warnings 12 | import requests 13 | from requests.auth import AuthBase 14 | 15 | from arcgis_exceptions import TokenAuthenticationError, TokenAuthenticationWarning 16 | 17 | # Python v3 commpatability 18 | try: 19 | from urllib import urlencode 20 | from urlparse import urlparse 21 | except: 22 | from urllib.parse import urlparse 23 | def urlencode(input_dict): 24 | return ('&'.join(['{}={}'.format(quote(k, safe='/'), quote(v, safe='/')) 25 | for k, v in input_dict.items()])) 26 | 27 | 28 | # Added this to be able to execute from PyScripter (which kept throwing errors about not being in a 'package'). 29 | ##try: 30 | ## from .arcgis_exceptions import TokenAuthenticationError, TokenAuthenticationWarning 31 | ##except: 32 | ## import sys 33 | ## from os import path 34 | ## sys.path.append( path.dirname( path.dirname( path.abspath(__file__) ) ) ) 35 | ## from arcgis_exceptions import TokenAuthenticationError, TokenAuthenticationWarning 36 | 37 | """ TODOS 38 | Try to securely pass it (with post in the body). Esri does not seem to support that on the admin interface. For now, just add to the URI parameters 39 | if username/pwd is wrong... dont keep re-requesting it... accounts get locked easily (3 failed login attempts)? 40 | """ 41 | 42 | """ NOTES 43 | will generate a token using the token URL from the FIRST REQUEST only at this point. 44 | Meaning the token object will not be able to be re-used between management interfaces (seperate ArcGIS for Server Sites) 45 | """ 46 | 47 | class ArcGISServerTokenAuth(AuthBase): 48 | # Esri ArcGIS for Server Authentication Handler to be used with the Requests Package 49 | """Python Requests Authentication Handler for the Esri ArcGIS Server product (Stand Alone). This class only supports the vendor proprietary 'Token Based' authentication. 50 | 51 | Args: 52 | username (:obj:`str`): Username of user authenticating. 53 | password (:obj:`str`): Password of user authenticating. 54 | verify (:obj:`bool`, Optional): Verify SSL Certificates (default: True). Use caution disabiling this (not reccomended for production use) 55 | instance (:obj:`str`, Optional): - The 'instance' name of the ArcGIS for Server Site (also known as the web-adaptor name). Code will attempt to derive if not supplied. ex: 'arcgis' 56 | """ 57 | def __init__(self,username,password,verify=True,instance=None): 58 | 59 | # Public attributes 60 | self.username=username 61 | self.password=password 62 | self.instance=instance # The 'instance' is also the 'web-adaptor' name. Defaults to 'arcgis'. Will be derived from the first URL request if not supplied. 63 | self.verify=verify 64 | 65 | # 'Private' Attributes 66 | self._token={} 67 | self._auth_info=None 68 | self._expires=datetime.fromtimestamp(int(time.time())-120) # Set to 2 min ago 69 | self._last_request=None 70 | self._redirect=None # Only used for debugging... possibly remove? 71 | 72 | @property 73 | def token(self): 74 | '''Return the access token''' 75 | return self._token.get("token") 76 | 77 | def __call__(self,r): 78 | 79 | # type(r) = PreparedRequest 80 | #print r.url 81 | 82 | self._init(r) 83 | 84 | # If the site does not support token authentication, then dont generate a token and just return the prepared request 85 | if not self._auth_info.get("isTokenBasedSecurity"): 86 | warnings.warn(("Unable to acquire token; site does not support token authentication"),TokenAuthenticationWarning) 87 | return r 88 | 89 | # Check token expiration and generate a new one if needed. If it expires within 2 min from now (a little padding) 90 | if (self._expires - datetime.now()).total_seconds() < 120: 91 | self._get_token(self._auth_info.get("tokenServicesUrl")) 92 | 93 | # Handle Re-Directs - See https://github.com/kennethreitz/requests/issues/4040 94 | r.register_hook('response', self.handle_redirect) 95 | 96 | self._add_token_to_request(r) 97 | return r 98 | 99 | def _init(self,r): 100 | 101 | # Only execute if after initialized (first request) - Derive Instance (if needed) & Authentication Info 102 | 103 | if self.instance is None: 104 | self._derive_instance(r) 105 | 106 | if self._auth_info is None: 107 | self._get_server_security_posture(r) 108 | 109 | 110 | def handle_redirect(self, r, **kwargs): 111 | 112 | # Handling Re-Direct!!! This was necessary because the method (POST) was not persisting on an HTTP 302 re-direct. See https://github.com/kennethreitz/requests/issues/4040 113 | # type(r) = Response 114 | 115 | if r.is_redirect: 116 | self._redirect=r 117 | req=r.request.copy() 118 | req.url=r.headers.get("Location") 119 | self._add_token_to_request(req) 120 | self._redirect_resend=r.connection.send(req,**kwargs) 121 | return self._redirect_resend 122 | return r 123 | 124 | def _add_token_to_request(self,r): 125 | 126 | 127 | ### ATTN !!! Only able to get this to work by adding the token to the URL parameters... not in the body... 128 | # GOAL was to Add the token to the body (encoded), although when the method is POST and the token is present in the body... the server returns: 129 | # {"status":"error","messages":["Unauthorized access. Token not found. You can generate a token using the 'generateToken' operation."],"code":499} 130 | #r.body=urlencode(self._token) if r.body is None else r.body+urlencode(self._token) 131 | 132 | # For now... Add the token as a URL Query parameter 133 | r.prepare_url(r.url,self._token) 134 | return r 135 | 136 | def _get_token(self,token_url): 137 | 138 | # Submit user credentials to acquire security token 139 | 140 | params={} 141 | params['f']='json' 142 | params['username']=self.username 143 | params['password']=self.password 144 | params['client']="requestip" # Possible Future TODO - Allow developer to specify a specific IP. Also... possibly allow developer to specify requested expiration... 145 | 146 | self._last_request=requests.post(token_url,data=urlencode(params),verify=self.verify,headers={"Content-type": "application/x-www-form-urlencoded","Accept": "text/plain"}) 147 | 148 | # Possible future TODO - Handle bad requests (invalid uname/pwd, etc) 149 | if self._last_request.json().get("error") is not None: 150 | err=self._last_request.json().get("error") 151 | raise TokenAuthenticationError("Unable to acquire token; {json}".format(json=str(err))) 152 | self._token['token']=self._last_request.json().get("token") 153 | 154 | # had to caset 'expires' to int as the /admin/generateToken returns as as a string... 155 | self._expires=datetime.fromtimestamp(int(self._last_request.json().get("expires"))/1000) 156 | 157 | def _get_url_string(self,r,path): 158 | 159 | # Add the path above to the 'instance'. The Path should can include a preceding '/' (or not) 160 | # !!! WARNING !!! Possible that we receive an array index exception if the path is an empty string... Possibly add future checks?? 161 | path=path[1:] if path[0] is "/" else path 162 | up=urlparse(r.url) 163 | return up.geturl().replace(up.path,"/%s/%s"%(self.instance,path)) 164 | 165 | def _derive_instance(self,r): 166 | 167 | # Need to determine the "instance" from the requesting URL, then security posture (info) endpoint. 168 | # Expected Inputs: 169 | # https://host/arcgis 170 | # https://host/arcgis/rest 171 | # https://host/arcgis/rest/services 172 | # https://host:port/* 173 | 174 | # Derive the 'Instance' (normally the first path element). This is the 'Web-Adaptor' name 175 | if self.instance is None: 176 | up=urlparse(r.url) 177 | self.instance = up.path.split("/")[1] 178 | 179 | def _get_server_security_posture(self,r,auth=None): 180 | 181 | # Query the server 'Info' to determine security posture 182 | server_info_url=self._get_url_string(r,"/rest/info") 183 | 184 | # Add f=json to parameters if not included in the URL string 185 | params={"f":"json"} if server_info_url.find("f=json") is -1 else {} 186 | self._last_request=requests.post(server_info_url,params=params,verify=self.verify,auth=auth) 187 | if self._last_request.status_code != 200: 188 | raise TokenAuthenticationError("Unable to acquire token; cannot determine site information at {url}. HTTP Status Code {sc}".format(url=server_info_url,sc=self._last_request.status_code)) 189 | 190 | if not 'authInfo' in self._last_request.json(): 191 | raise TokenAuthenticationError("Unable to acquire token; authInfo JSON Key unavailable at {url}. HTTP Status Code {sc}".format(url=server_info_url,sc=self._last_request.status_code)) 192 | 193 | self._auth_info = self._last_request.json().get('authInfo') 194 | #print self._auth_info 195 | 196 | # Deal with admin endpoint (issue #34) by checking for the /admin/ in the url path (second position) 197 | up=urlparse(r.url) 198 | if (up.path.split("/")[2] == 'admin'): 199 | self._auth_info['tokenServicesUrl'] = self._get_url_string(r,'/admin/generateToken') 200 | 201 | 202 | class ArcGISPortalTokenAuth(AuthBase): 203 | # Esri ArcGIS Portal (and ArcGIS Online) Authentication Handler to be used with the Requests Package 204 | 205 | """Python Requests Authentication Handler for the Esri Portal for ArcGIS product and ArcGIS Online. This class only supports the vendor proprietary 'Token Based' authentication. 206 | 207 | Args: 208 | username (:obj:`str`): Username of user authenticating. 209 | password (:obj:`str`): Password of user authenticating. 210 | verify (:obj:`bool`, Optional): Verify SSL Certificates (default: True). Use caution disabiling this (not reccomended for production use) 211 | instance (:obj:`str`, Optional): - The 'instance' name of the ArcGIS for Server Site (also known as the web-adaptor name). Code will attempt to derive if not supplied. ex: 'portal' 212 | """ 213 | 214 | def __init__(self,username,password,verify=True,instance=None): 215 | 216 | # Public Attributes 217 | self.username=username 218 | self.password=password 219 | self.instance=instance # The 'instance' is also the 'web-adaptor' name. Defaults to 'arcgis'. Will be derived from the first URL request if not supplied. 220 | self.verify=verify 221 | 222 | # 'Private' Attributes 223 | self._token={} 224 | self._expires=datetime.fromtimestamp(int(time.time())-120) # Set to 2 min ago 225 | self._last_request=None 226 | self._redirect=None # Only used for debugging... possibly remove? 227 | 228 | def __call__(self,r): 229 | 230 | # type(r) = PreparedRequest 231 | 232 | self._init(r) 233 | 234 | # Check token expiration and generate a new one if needed. If it expires within 2 min from now (a little padding) 235 | if (self._expires - datetime.now()).total_seconds() < 120: 236 | self._get_token(self._get_token_url(r)) 237 | 238 | # Handle Re-Directs - See https://github.com/kennethreitz/requests/issues/4040 239 | r.register_hook('response', self.handle_redirect) 240 | 241 | self._add_token_to_request(r) 242 | return r 243 | 244 | def _init(self,r): 245 | 246 | # Only execute if after initialized (first request) - Derive Instance (if needed) & Authentication Info 247 | 248 | if self.instance is None: 249 | self._derive_instance(r) 250 | 251 | def handle_redirect(self, r, **kwargs): 252 | 253 | # Handling Re-Direct!!! This was necessary because the method (POST) was not persisting on an HTTP 302 re-direct. See https://github.com/kennethreitz/requests/issues/4040 254 | # type(r) = Response 255 | if r.is_redirect: 256 | self._redirect=r 257 | req=r.request.copy() 258 | req.url=r.headers.get("Location") 259 | self._add_token_to_request(req) 260 | self._redirect_resend=r.connection.send(req,**kwargs) 261 | return self._redirect_resend 262 | return r 263 | 264 | def _add_token_to_request(self,r): 265 | 266 | 267 | ### ATTN !!! Only able to get this to work by adding the token to the URL parameters... not in the body... 268 | # GOAL was to Add the token to the body (encoded), although when the method is POST and the token is present in the body... the server returns: 269 | # {"status":"error","messages":["Unauthorized access. Token not found. You can generate a token using the 'generateToken' operation."],"code":499} 270 | #r.body=urlencode(self._token) if r.body is None else r.body+urlencode(self._token) 271 | 272 | # For now... Add the token as a URL Query parameter 273 | r.prepare_url(r.url,self._token) 274 | return r 275 | 276 | def _get_token_url(self,r): 277 | up=urlparse(r.url) 278 | return up.geturl().replace(up.path,"/%s%s"%(self.instance,"/sharing/rest/generateToken")) 279 | 280 | def _get_token(self,token_url): 281 | # print "getting Token" 282 | # Submit user credentials to acquire security token 283 | params={} 284 | params['f']='json' 285 | params['username']=self.username 286 | params['password']=self.password 287 | params['client']="requestip" # Possible Future TODO - Allow developer to specify a specific IP. Also... possibly allow developer to specify requested expiration... 288 | 289 | self._last_request=requests.post(token_url,data=urlencode(params),verify=self.verify,headers={"Content-type": "application/x-www-form-urlencoded","Accept": "text/plain"}) 290 | 291 | # Possible future TODO - Handle bad requests (invalid uname/pwd, etc) 292 | if self._last_request.json().get("error") is not None: 293 | err=self._last_request.json().get("error") 294 | raise TokenAuthenticationError("Unable to acquire token; {json}".format(json=str(err))) 295 | self._token['token']=self._last_request.json().get("token") 296 | self._expires=datetime.fromtimestamp(self._last_request.json().get("expires")/1000) 297 | 298 | 299 | def _derive_instance(self,r): 300 | 301 | # Need to determine the "instance" from the requesting URL, then security posture (info) endpoint. 302 | # Expected Inputs: 303 | # https://host/arcgis 304 | # https://host/arcgis/sharing 305 | # https://host/arcgis/sharing/rest 306 | # https://host:port/sharing/rest 307 | 308 | # Derive the 'Instance' (normally the first path element), unless it is "sharing" (ex: AGOL). This is the 'Web-Adaptor' name for on-premise portals 309 | if self.instance is None: 310 | up=urlparse(r.url) 311 | path1=up.path.split("/")[1] 312 | self.instance = path1 if path1 != "sharing" else "" 313 | 314 | 315 | -------------------------------------------------------------------------------- /requests_arcgis_auth/test/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DOI-BLM/requests-arcgis-auth/e01c7b708638562efebb67b54a1f8a3bbcd1eff0/requests_arcgis_auth/test/__init__.py -------------------------------------------------------------------------------- /requests_arcgis_auth/test/packages/colorama-0.3.9/CHANGELOG.rst: -------------------------------------------------------------------------------- 1 | 0.3.9 2 | * Revert fix for issue #103 which causes problems for dependent applications 3 | 0.3.8 4 | * Fix issue #121: "invalid escape sequence" deprecation fixes on Python 3.6+ 5 | * Fix issue #110: fix "set console title" when working with unicode strings 6 | * Fix issue #103: enable color when using "input" function on Python 3.5+ 7 | * Fix issue #95: enable color when stderr is a tty but stdout is not 8 | 0.3.7 9 | * Fix issue #84: check if stream has 'closed' attribute before testing it 10 | * Fix issue #74: objects might become None at exit 11 | 0.3.6 12 | * Fix issue #81: fix ValueError when a closed stream was used 13 | 0.3.5 14 | * Bumping version to re-upload a wheel distribution 15 | 0.3.4 16 | * Fix issue #47 and #80 - stream redirection now strips ANSI codes on Linux 17 | * Fix issue #53 - strip readline markers 18 | * Fix issue #32 - assign orig_stdout and orig_stderr when initialising 19 | * Fix issue #57 - Fore.RESET did not reset style of LIGHT_EX colors. 20 | Fixed by Andy Neff 21 | * Fix issue #51 - add context manager syntax. Thanks to Matt Olsen. 22 | * Fix issue #48 - colorama didn't work on Windows when environment 23 | variable 'TERM' was set. 24 | * Fix issue #54 - fix pylint errors in client code. 25 | * Changes to readme and other improvements by Marc Abramowitz and Zearin 26 | 0.3.3 27 | * Fix Google Code issue #13 - support changing the console title with OSC 28 | escape sequence 29 | * Fix Google Code issue #16 - Add support for Windows xterm emulators 30 | * Fix Google Code issue #30 - implement \033[nK (clear line) 31 | * Fix Google Code issue #49 - no need to adjust for scroll when new position 32 | is already relative (CSI n A\B\C\D) 33 | * Fix Google Code issue #55 - erase_data fails on Python 3.x 34 | * Fix Google Code issue #46 - win32.COORD definition missing 35 | * Implement \033[0J and \033[1J (clear screen options) 36 | * Fix default ANSI parameters 37 | * Fix position after \033[2J (clear screen) 38 | * Add command shortcuts: colorama.Cursor, colorama.ansi.set_title, 39 | colorama.ansi.clear_line, colorama.ansi.clear_screen 40 | * Fix issue #22 - Importing fails for python3 on Windows 41 | * Thanks to John Szakmeister for adding support for light colors 42 | * Thanks to Charles Merriam for adding documentation to demos 43 | 0.3.2 44 | * Thanks to Marc Schlaich (schlamar) for a setup.py fix for Python2.5 45 | * Thanks to Jurko for fix on 64-bit Windows CPython2.5 w/o ctypes 46 | (Google Code issue #56) 47 | * Thanks to Remi Rampin for: 48 | * better github integration, incl rendered README and Travis config. 49 | * fixed forward slashes in README 50 | * Thanks to Florian Bruhin for fix when stdout or stderr are None 51 | * Thanks to Simeon Visser for: 52 | * closing a file handle using 'with' 53 | * updating classifiers to include Python 3.3 and 3.4 54 | * Thanks to Thomas Weininger for fix ValueError on Windows 55 | (Google Code issue #50) 56 | 0.3.1 57 | * Fixed crash on exit with closed stdout, with thanks to Marc Abramowitz. 58 | * Now uses setuptools if available, and falls back to distutils if not. 59 | * setup.py no longer imports anything from colorama source. 60 | 0.3.0 61 | * Move repository to Git, https://github.com/tartley/colorama. (My Mercurial 62 | repo seemed to be corrupted, I couldn't commit nor view patches of old 63 | commits, even on fresh checkouts.) 64 | * Fix always-crash on non-Windows platforms, reported by Matt McCormick. 65 | * Fix Google Code issue #47, incompatible with pyreadline. 66 | 0.2.7 67 | * Fix problem under 64-bit windows due to ctypes HANDLE size. 68 | Submitted by the rather magnificent Ben Hoyt. 69 | This fixes Google Code issue #43 70 | 0.2.6 71 | * Add copyright & licensing info to every file, as requested by a large 72 | downstream project which has problems making sure that all 3rd party 73 | contributions have appropriate license. 74 | 0.2.5 75 | * Severeral documentation & demo fixes. 76 | 0.2.4 77 | * Fix to work on Windows 7. 78 | * Python 3 compatibility in docs and demos. 79 | * Add handling for 'cursor up' and 'get position' ANSI codes. 80 | 0.2.3 81 | * Split changelog out into separate file. 82 | 0.2.2 83 | * Fix bug which caused init() to raise, introduced in 0.2.1. 84 | * Remove asserts which cause problems in various circumstances. At least 85 | some users saw asserts fail on 'success' returned from win32 functions, 86 | even though the win32 functions appear to have worked correctly. 87 | 0.2.1 88 | * Completely broken: I added a bug which caused init() to raise. 89 | * Added some documentation for cursor positioning and clear screen to README. 90 | * Add 'reinit' and 'deinit' functions, as suggested by Charles FOL and 91 | Romanov DA. 92 | 0.2 93 | * Merge in changes from Daniel Griffith: Add ANSI cursor positioning & 94 | partial support for clear screen. Patch submitted by Oscar Lester, don't 95 | send RESET_ALL to non-tty. 96 | * Demos split into separate files and moved into their own directory. 97 | * Tweak sys.path in demos so they run against local source, not installed 98 | version of Colorama. 99 | 0.1.18 100 | * Fix README (no such attr as Fore.DEFAULT, etc), kindly reported by nodakai. 101 | 0.1.17 102 | * Prevent printing of garbage ANSI codes upon installing with pip 103 | 0.1.16 104 | * Re-upload to fix previous error. Make clean now removes old MANIFEST. 105 | 0.1.15 106 | * Completely broken. Distribution was empty due to leftover invalid MANIFEST 107 | file from building on a different platform. 108 | * Fix python3 incompatibility kindly reported by G |uumlaut| nter Kolousek 109 | 0.1.14 110 | * Fix hard-coded reset to white-on-black colors. Fore.RESET, Back.RESET 111 | and Style.RESET_ALL now revert to the colors as they were when init() 112 | was called. Some lessons hopefully learned about testing prior to release. 113 | 0.1.13 114 | * Completely broken: barfed when installed using pip. 115 | 0.1.12 116 | * Completely broken: contained no source code. double oops. 117 | 0.1.11 118 | * Completely broken: fatal import errors on Ubuntu. oops. 119 | 0.1.10 120 | * Stop emulating 'bright' text with bright backgrounds. 121 | * Display 'normal' text using win32 normal foreground instead of bright. 122 | * Drop support for 'dim' text. 123 | 0.1.9 124 | * Fix incompatibility with Python 2.5 and earlier. 125 | * Remove setup.py dependency on setuptools, now uses stdlib distutils. 126 | 0.1.8 127 | * Fix ghastly errors all over the place on Ubuntu. 128 | * Add init kwargs 'convert' and 'strip', which supercede the old 'wrap'. 129 | 0.1.7 130 | * Python 3 compatible. 131 | * Fix: Now strips ansi on windows without necessarily converting it to 132 | win32 calls (eg. if output is not a tty.) 133 | * Fix: Flaky interaction of interleaved ansi sent to stdout and stderr. 134 | * Improved demo.sh (hg checkout only.) 135 | 0.1.6 136 | * Fix ansi sequences with no params now default to parmlist of [0]. 137 | * Fix flaky behaviour of autoreset and reset_all atexit. 138 | * Fix stacking of repeated atexit calls - now just called once. 139 | * Fix ghastly import problems while running tests. 140 | * 'demo.py' (hg checkout only) now demonstrates autoreset and reset atexit. 141 | * Provide colorama.VERSION, used by setup.py. 142 | * Tests defanged so they no longer actually change terminal color when run. 143 | 0.1.5 144 | * Now works on Ubuntu. 145 | 0.1.4 146 | * Implemented RESET_ALL on application exit 147 | 0.1.3 148 | * Implemented init(wrap=False) 149 | 0.1.2 150 | * Implemented init(autoreset=True) 151 | 0.1.1 152 | * Minor tidy 153 | 0.1 154 | * Works on Windows for foreground color, background color, bright or dim 155 | 156 | 157 | .. |uumlaut| unicode:: U+00FC .. u with umlaut 158 | :trim: 159 | 160 | -------------------------------------------------------------------------------- /requests_arcgis_auth/test/packages/colorama-0.3.9/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2010 Jonathan Hartley 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | * Neither the name of the copyright holders, nor those of its contributors 15 | may be used to endorse or promote products derived from this software without 16 | specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 19 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | -------------------------------------------------------------------------------- /requests_arcgis_auth/test/packages/colorama-0.3.9/MANIFEST.in: -------------------------------------------------------------------------------- 1 | include LICENSE.txt CHANGELOG.rst 2 | recursive-include demos *.py *.bat *.sh 3 | 4 | -------------------------------------------------------------------------------- /requests_arcgis_auth/test/packages/colorama-0.3.9/README.rst: -------------------------------------------------------------------------------- 1 | .. image:: https://img.shields.io/pypi/v/colorama.svg 2 | :target: https://pypi.python.org/pypi/colorama/ 3 | :alt: Latest Version 4 | 5 | .. image:: https://travis-ci.org/tartley/colorama.svg?branch=master 6 | :target: https://travis-ci.org/tartley/colorama 7 | :alt: Build Status 8 | 9 | Download and docs: 10 | http://pypi.python.org/pypi/colorama 11 | Source code & Development: 12 | https://github.com/tartley/colorama 13 | 14 | Description 15 | =========== 16 | 17 | Makes ANSI escape character sequences (for producing colored terminal text and 18 | cursor positioning) work under MS Windows. 19 | 20 | ANSI escape character sequences have long been used to produce colored terminal 21 | text and cursor positioning on Unix and Macs. Colorama makes this work on 22 | Windows, too, by wrapping ``stdout``, stripping ANSI sequences it finds (which 23 | would appear as gobbledygook in the output), and converting them into the 24 | appropriate win32 calls to modify the state of the terminal. On other platforms, 25 | Colorama does nothing. 26 | 27 | Colorama also provides some shortcuts to help generate ANSI sequences 28 | but works fine in conjunction with any other ANSI sequence generation library, 29 | such as the venerable Termcolor (http://pypi.python.org/pypi/termcolor) 30 | or the fabulous Blessings (https://pypi.python.org/pypi/blessings). 31 | 32 | This has the upshot of providing a simple cross-platform API for printing 33 | colored terminal text from Python, and has the happy side-effect that existing 34 | applications or libraries which use ANSI sequences to produce colored output on 35 | Linux or Macs can now also work on Windows, simply by calling 36 | ``colorama.init()``. 37 | 38 | An alternative approach is to install ``ansi.sys`` on Windows machines, which 39 | provides the same behaviour for all applications running in terminals. Colorama 40 | is intended for situations where that isn't easy (e.g., maybe your app doesn't 41 | have an installer.) 42 | 43 | Demo scripts in the source code repository print some colored text using 44 | ANSI sequences. Compare their output under Gnome-terminal's built in ANSI 45 | handling, versus on Windows Command-Prompt using Colorama: 46 | 47 | .. image:: https://github.com/tartley/colorama/raw/master/screenshots/ubuntu-demo.png 48 | :width: 661 49 | :height: 357 50 | :alt: ANSI sequences on Ubuntu under gnome-terminal. 51 | 52 | .. image:: https://github.com/tartley/colorama/raw/master/screenshots/windows-demo.png 53 | :width: 668 54 | :height: 325 55 | :alt: Same ANSI sequences on Windows, using Colorama. 56 | 57 | These screengrabs show that, on Windows, Colorama does not support ANSI 'dim 58 | text'; it looks the same as 'normal text'. 59 | 60 | 61 | License 62 | ======= 63 | 64 | Copyright Jonathan Hartley 2013. BSD 3-Clause license; see LICENSE file. 65 | 66 | 67 | Dependencies 68 | ============ 69 | 70 | None, other than Python. Tested on Python 2.5.5, 2.6.5, 2.7, 3.1.2, 3.2, 3.3, 71 | 3.4 and 3.5. 72 | 73 | Usage 74 | ===== 75 | 76 | Initialisation 77 | -------------- 78 | 79 | Applications should initialise Colorama using: 80 | 81 | .. code-block:: python 82 | 83 | from colorama import init 84 | init() 85 | 86 | On Windows, calling ``init()`` will filter ANSI escape sequences out of any 87 | text sent to ``stdout`` or ``stderr``, and replace them with equivalent Win32 88 | calls. 89 | 90 | On other platforms, calling ``init()`` has no effect (unless you request other 91 | optional functionality; see "Init Keyword Args", below). By design, this permits 92 | applications to call ``init()`` unconditionally on all platforms, after which 93 | ANSI output should just work. 94 | 95 | To stop using colorama before your program exits, simply call ``deinit()``. 96 | This will restore ``stdout`` and ``stderr`` to their original values, so that 97 | Colorama is disabled. To resume using Colorama again, call ``reinit()``; it is 98 | cheaper to calling ``init()`` again (but does the same thing). 99 | 100 | 101 | Colored Output 102 | -------------- 103 | 104 | Cross-platform printing of colored text can then be done using Colorama's 105 | constant shorthand for ANSI escape sequences: 106 | 107 | .. code-block:: python 108 | 109 | from colorama import Fore, Back, Style 110 | print(Fore.RED + 'some red text') 111 | print(Back.GREEN + 'and with a green background') 112 | print(Style.DIM + 'and in dim text') 113 | print(Style.RESET_ALL) 114 | print('back to normal now') 115 | 116 | ...or simply by manually printing ANSI sequences from your own code: 117 | 118 | .. code-block:: python 119 | 120 | print('\033[31m' + 'some red text') 121 | print('\033[30m') # and reset to default color 122 | 123 | ...or, Colorama can be used happily in conjunction with existing ANSI libraries 124 | such as Termcolor: 125 | 126 | .. code-block:: python 127 | 128 | from colorama import init 129 | from termcolor import colored 130 | 131 | # use Colorama to make Termcolor work on Windows too 132 | init() 133 | 134 | # then use Termcolor for all colored text output 135 | print(colored('Hello, World!', 'green', 'on_red')) 136 | 137 | Available formatting constants are:: 138 | 139 | Fore: BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE, RESET. 140 | Back: BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE, RESET. 141 | Style: DIM, NORMAL, BRIGHT, RESET_ALL 142 | 143 | ``Style.RESET_ALL`` resets foreground, background, and brightness. Colorama will 144 | perform this reset automatically on program exit. 145 | 146 | 147 | Cursor Positioning 148 | ------------------ 149 | 150 | ANSI codes to reposition the cursor are supported. See ``demos/demo06.py`` for 151 | an example of how to generate them. 152 | 153 | 154 | Init Keyword Args 155 | ----------------- 156 | 157 | ``init()`` accepts some ``**kwargs`` to override default behaviour. 158 | 159 | init(autoreset=False): 160 | If you find yourself repeatedly sending reset sequences to turn off color 161 | changes at the end of every print, then ``init(autoreset=True)`` will 162 | automate that: 163 | 164 | .. code-block:: python 165 | 166 | from colorama import init 167 | init(autoreset=True) 168 | print(Fore.RED + 'some red text') 169 | print('automatically back to default color again') 170 | 171 | init(strip=None): 172 | Pass ``True`` or ``False`` to override whether ansi codes should be 173 | stripped from the output. The default behaviour is to strip if on Windows 174 | or if output is redirected (not a tty). 175 | 176 | init(convert=None): 177 | Pass ``True`` or ``False`` to override whether to convert ANSI codes in the 178 | output into win32 calls. The default behaviour is to convert if on Windows 179 | and output is to a tty (terminal). 180 | 181 | init(wrap=True): 182 | On Windows, colorama works by replacing ``sys.stdout`` and ``sys.stderr`` 183 | with proxy objects, which override the ``.write()`` method to do their work. 184 | If this wrapping causes you problems, then this can be disabled by passing 185 | ``init(wrap=False)``. The default behaviour is to wrap if ``autoreset`` or 186 | ``strip`` or ``convert`` are True. 187 | 188 | When wrapping is disabled, colored printing on non-Windows platforms will 189 | continue to work as normal. To do cross-platform colored output, you can 190 | use Colorama's ``AnsiToWin32`` proxy directly: 191 | 192 | .. code-block:: python 193 | 194 | import sys 195 | from colorama import init, AnsiToWin32 196 | init(wrap=False) 197 | stream = AnsiToWin32(sys.stderr).stream 198 | 199 | # Python 2 200 | print >>stream, Fore.BLUE + 'blue text on stderr' 201 | 202 | # Python 3 203 | print(Fore.BLUE + 'blue text on stderr', file=stream) 204 | 205 | 206 | Status & Known Problems 207 | ======================= 208 | 209 | I've personally only tested it on Windows XP (CMD, Console2), Ubuntu 210 | (gnome-terminal, xterm), and OS X. 211 | 212 | Some presumably valid ANSI sequences aren't recognised (see details below), 213 | but to my knowledge nobody has yet complained about this. Puzzling. 214 | 215 | See outstanding issues and wishlist: 216 | https://github.com/tartley/colorama/issues 217 | 218 | If anything doesn't work for you, or doesn't do what you expected or hoped for, 219 | I'd love to hear about it on that issues list, would be delighted by patches, 220 | and would be happy to grant commit access to anyone who submits a working patch 221 | or two. 222 | 223 | 224 | Recognised ANSI Sequences 225 | ========================= 226 | 227 | ANSI sequences generally take the form: 228 | 229 | ESC [ ; ... 230 | 231 | Where ```` is an integer, and ```` is a single letter. Zero or 232 | more params are passed to a ````. If no params are passed, it is 233 | generally synonymous with passing a single zero. No spaces exist in the 234 | sequence; they have been inserted here simply to read more easily. 235 | 236 | The only ANSI sequences that colorama converts into win32 calls are:: 237 | 238 | ESC [ 0 m # reset all (colors and brightness) 239 | ESC [ 1 m # bright 240 | ESC [ 2 m # dim (looks same as normal brightness) 241 | ESC [ 22 m # normal brightness 242 | 243 | # FOREGROUND: 244 | ESC [ 30 m # black 245 | ESC [ 31 m # red 246 | ESC [ 32 m # green 247 | ESC [ 33 m # yellow 248 | ESC [ 34 m # blue 249 | ESC [ 35 m # magenta 250 | ESC [ 36 m # cyan 251 | ESC [ 37 m # white 252 | ESC [ 39 m # reset 253 | 254 | # BACKGROUND 255 | ESC [ 40 m # black 256 | ESC [ 41 m # red 257 | ESC [ 42 m # green 258 | ESC [ 43 m # yellow 259 | ESC [ 44 m # blue 260 | ESC [ 45 m # magenta 261 | ESC [ 46 m # cyan 262 | ESC [ 47 m # white 263 | ESC [ 49 m # reset 264 | 265 | # cursor positioning 266 | ESC [ y;x H # position cursor at x across, y down 267 | ESC [ y;x f # position cursor at x across, y down 268 | ESC [ n A # move cursor n lines up 269 | ESC [ n B # move cursor n lines down 270 | ESC [ n C # move cursor n characters forward 271 | ESC [ n D # move cursor n characters backward 272 | 273 | # clear the screen 274 | ESC [ mode J # clear the screen 275 | 276 | # clear the line 277 | ESC [ mode K # clear the line 278 | 279 | Multiple numeric params to the ``'m'`` command can be combined into a single 280 | sequence:: 281 | 282 | ESC [ 36 ; 45 ; 1 m # bright cyan text on magenta background 283 | 284 | All other ANSI sequences of the form ``ESC [ ; ... `` 285 | are silently stripped from the output on Windows. 286 | 287 | Any other form of ANSI sequence, such as single-character codes or alternative 288 | initial characters, are not recognised or stripped. It would be cool to add 289 | them though. Let me know if it would be useful for you, via the Issues on 290 | GitHub. 291 | 292 | 293 | Development 294 | =========== 295 | 296 | Help and fixes welcome! 297 | 298 | Running tests requires: 299 | 300 | - Michael Foord's ``mock`` module to be installed. 301 | - Tests are written using 2010-era updates to ``unittest``, and require 302 | Python 2.7 or greater, OR to have Michael Foord's ``unittest2`` module 303 | installed. 304 | 305 | To run tests:: 306 | 307 | python -m unittest discover -p *_test.py 308 | 309 | This, like a few other handy commands, is captured in a ``Makefile``. 310 | 311 | If you use nose to run the tests, you must pass the ``-s`` flag; otherwise, 312 | ``nosetests`` applies its own proxy to ``stdout``, which confuses the unit 313 | tests. 314 | 315 | 316 | Thanks 317 | ====== 318 | * Marc Schlaich (schlamar) for a ``setup.py`` fix for Python2.5. 319 | * Marc Abramowitz, reported & fixed a crash on exit with closed ``stdout``, 320 | providing a solution to issue #7's setuptools/distutils debate, 321 | and other fixes. 322 | * User 'eryksun', for guidance on correctly instantiating ``ctypes.windll``. 323 | * Matthew McCormick for politely pointing out a longstanding crash on non-Win. 324 | * Ben Hoyt, for a magnificent fix under 64-bit Windows. 325 | * Jesse at Empty Square for submitting a fix for examples in the README. 326 | * User 'jamessp', an observant documentation fix for cursor positioning. 327 | * User 'vaal1239', Dave Mckee & Lackner Kristof for a tiny but much-needed Win7 328 | fix. 329 | * Julien Stuyck, for wisely suggesting Python3 compatible updates to README. 330 | * Daniel Griffith for multiple fabulous patches. 331 | * Oscar Lesta for a valuable fix to stop ANSI chars being sent to non-tty 332 | output. 333 | * Roger Binns, for many suggestions, valuable feedback, & bug reports. 334 | * Tim Golden for thought and much appreciated feedback on the initial idea. 335 | * User 'Zearin' for updates to the README file. 336 | * John Szakmeister for adding support for light colors 337 | * Charles Merriam for adding documentation to demos 338 | * Jurko for a fix on 64-bit Windows CPython2.5 w/o ctypes 339 | * Florian Bruhin for a fix when stdout or stderr are None 340 | * Thomas Weininger for fixing ValueError on Windows 341 | * Remi Rampin for better Github integration and fixes to the README file 342 | * Simeon Visser for closing a file handle using 'with' and updating classifiers 343 | to include Python 3.3 and 3.4 344 | * Andy Neff for fixing RESET of LIGHT_EX colors. 345 | * Jonathan Hartley for the initial idea and implementation. 346 | 347 | -------------------------------------------------------------------------------- /requests_arcgis_auth/test/packages/colorama-0.3.9/colorama.egg-info/SOURCES.txt: -------------------------------------------------------------------------------- 1 | CHANGELOG.rst 2 | LICENSE.txt 3 | MANIFEST.in 4 | README.rst 5 | setup.cfg 6 | setup.py 7 | colorama/__init__.py 8 | colorama/ansi.py 9 | colorama/ansitowin32.py 10 | colorama/initialise.py 11 | colorama/win32.py 12 | colorama/winterm.py 13 | colorama.egg-info/PKG-INFO 14 | colorama.egg-info/SOURCES.txt 15 | colorama.egg-info/dependency_links.txt 16 | colorama.egg-info/pbr.json 17 | colorama.egg-info/top_level.txt 18 | demos/demo.bat 19 | demos/demo.sh 20 | demos/demo01.py 21 | demos/demo02.py 22 | demos/demo03.py 23 | demos/demo04.py 24 | demos/demo05.py 25 | demos/demo06.py 26 | demos/demo07.py 27 | demos/demo08.py 28 | demos/fixpath.py -------------------------------------------------------------------------------- /requests_arcgis_auth/test/packages/colorama-0.3.9/colorama.egg-info/dependency_links.txt: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /requests_arcgis_auth/test/packages/colorama-0.3.9/colorama.egg-info/pbr.json: -------------------------------------------------------------------------------- 1 | {"is_release": false, "git_version": "69e4069"} -------------------------------------------------------------------------------- /requests_arcgis_auth/test/packages/colorama-0.3.9/colorama.egg-info/top_level.txt: -------------------------------------------------------------------------------- 1 | colorama 2 | -------------------------------------------------------------------------------- /requests_arcgis_auth/test/packages/colorama-0.3.9/colorama/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. 2 | from .initialise import init, deinit, reinit, colorama_text 3 | from .ansi import Fore, Back, Style, Cursor 4 | from .ansitowin32 import AnsiToWin32 5 | 6 | __version__ = '0.3.9' 7 | 8 | -------------------------------------------------------------------------------- /requests_arcgis_auth/test/packages/colorama-0.3.9/colorama/ansi.py: -------------------------------------------------------------------------------- 1 | # Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. 2 | ''' 3 | This module generates ANSI character codes to printing colors to terminals. 4 | See: http://en.wikipedia.org/wiki/ANSI_escape_code 5 | ''' 6 | 7 | CSI = '\033[' 8 | OSC = '\033]' 9 | BEL = '\007' 10 | 11 | 12 | def code_to_chars(code): 13 | return CSI + str(code) + 'm' 14 | 15 | def set_title(title): 16 | return OSC + '2;' + title + BEL 17 | 18 | def clear_screen(mode=2): 19 | return CSI + str(mode) + 'J' 20 | 21 | def clear_line(mode=2): 22 | return CSI + str(mode) + 'K' 23 | 24 | 25 | class AnsiCodes(object): 26 | def __init__(self): 27 | # the subclasses declare class attributes which are numbers. 28 | # Upon instantiation we define instance attributes, which are the same 29 | # as the class attributes but wrapped with the ANSI escape sequence 30 | for name in dir(self): 31 | if not name.startswith('_'): 32 | value = getattr(self, name) 33 | setattr(self, name, code_to_chars(value)) 34 | 35 | 36 | class AnsiCursor(object): 37 | def UP(self, n=1): 38 | return CSI + str(n) + 'A' 39 | def DOWN(self, n=1): 40 | return CSI + str(n) + 'B' 41 | def FORWARD(self, n=1): 42 | return CSI + str(n) + 'C' 43 | def BACK(self, n=1): 44 | return CSI + str(n) + 'D' 45 | def POS(self, x=1, y=1): 46 | return CSI + str(y) + ';' + str(x) + 'H' 47 | 48 | 49 | class AnsiFore(AnsiCodes): 50 | BLACK = 30 51 | RED = 31 52 | GREEN = 32 53 | YELLOW = 33 54 | BLUE = 34 55 | MAGENTA = 35 56 | CYAN = 36 57 | WHITE = 37 58 | RESET = 39 59 | 60 | # These are fairly well supported, but not part of the standard. 61 | LIGHTBLACK_EX = 90 62 | LIGHTRED_EX = 91 63 | LIGHTGREEN_EX = 92 64 | LIGHTYELLOW_EX = 93 65 | LIGHTBLUE_EX = 94 66 | LIGHTMAGENTA_EX = 95 67 | LIGHTCYAN_EX = 96 68 | LIGHTWHITE_EX = 97 69 | 70 | 71 | class AnsiBack(AnsiCodes): 72 | BLACK = 40 73 | RED = 41 74 | GREEN = 42 75 | YELLOW = 43 76 | BLUE = 44 77 | MAGENTA = 45 78 | CYAN = 46 79 | WHITE = 47 80 | RESET = 49 81 | 82 | # These are fairly well supported, but not part of the standard. 83 | LIGHTBLACK_EX = 100 84 | LIGHTRED_EX = 101 85 | LIGHTGREEN_EX = 102 86 | LIGHTYELLOW_EX = 103 87 | LIGHTBLUE_EX = 104 88 | LIGHTMAGENTA_EX = 105 89 | LIGHTCYAN_EX = 106 90 | LIGHTWHITE_EX = 107 91 | 92 | 93 | class AnsiStyle(AnsiCodes): 94 | BRIGHT = 1 95 | DIM = 2 96 | NORMAL = 22 97 | RESET_ALL = 0 98 | 99 | Fore = AnsiFore() 100 | Back = AnsiBack() 101 | Style = AnsiStyle() 102 | Cursor = AnsiCursor() 103 | -------------------------------------------------------------------------------- /requests_arcgis_auth/test/packages/colorama-0.3.9/colorama/ansitowin32.py: -------------------------------------------------------------------------------- 1 | # Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. 2 | import re 3 | import sys 4 | import os 5 | 6 | from .ansi import AnsiFore, AnsiBack, AnsiStyle, Style 7 | from .winterm import WinTerm, WinColor, WinStyle 8 | from .win32 import windll, winapi_test 9 | 10 | 11 | winterm = None 12 | if windll is not None: 13 | winterm = WinTerm() 14 | 15 | 16 | def is_stream_closed(stream): 17 | return not hasattr(stream, 'closed') or stream.closed 18 | 19 | 20 | def is_a_tty(stream): 21 | return hasattr(stream, 'isatty') and stream.isatty() 22 | 23 | 24 | class StreamWrapper(object): 25 | ''' 26 | Wraps a stream (such as stdout), acting as a transparent proxy for all 27 | attribute access apart from method 'write()', which is delegated to our 28 | Converter instance. 29 | ''' 30 | def __init__(self, wrapped, converter): 31 | # double-underscore everything to prevent clashes with names of 32 | # attributes on the wrapped stream object. 33 | self.__wrapped = wrapped 34 | self.__convertor = converter 35 | 36 | def __getattr__(self, name): 37 | return getattr(self.__wrapped, name) 38 | 39 | def write(self, text): 40 | self.__convertor.write(text) 41 | 42 | 43 | class AnsiToWin32(object): 44 | ''' 45 | Implements a 'write()' method which, on Windows, will strip ANSI character 46 | sequences from the text, and if outputting to a tty, will convert them into 47 | win32 function calls. 48 | ''' 49 | ANSI_CSI_RE = re.compile('\001?\033\\[((?:\\d|;)*)([a-zA-Z])\002?') # Control Sequence Introducer 50 | ANSI_OSC_RE = re.compile('\001?\033\\]((?:.|;)*?)(\x07)\002?') # Operating System Command 51 | 52 | def __init__(self, wrapped, convert=None, strip=None, autoreset=False): 53 | # The wrapped stream (normally sys.stdout or sys.stderr) 54 | self.wrapped = wrapped 55 | 56 | # should we reset colors to defaults after every .write() 57 | self.autoreset = autoreset 58 | 59 | # create the proxy wrapping our output stream 60 | self.stream = StreamWrapper(wrapped, self) 61 | 62 | on_windows = os.name == 'nt' 63 | # We test if the WinAPI works, because even if we are on Windows 64 | # we may be using a terminal that doesn't support the WinAPI 65 | # (e.g. Cygwin Terminal). In this case it's up to the terminal 66 | # to support the ANSI codes. 67 | conversion_supported = on_windows and winapi_test() 68 | 69 | # should we strip ANSI sequences from our output? 70 | if strip is None: 71 | strip = conversion_supported or (not is_stream_closed(wrapped) and not is_a_tty(wrapped)) 72 | self.strip = strip 73 | 74 | # should we should convert ANSI sequences into win32 calls? 75 | if convert is None: 76 | convert = conversion_supported and not is_stream_closed(wrapped) and is_a_tty(wrapped) 77 | self.convert = convert 78 | 79 | # dict of ansi codes to win32 functions and parameters 80 | self.win32_calls = self.get_win32_calls() 81 | 82 | # are we wrapping stderr? 83 | self.on_stderr = self.wrapped is sys.stderr 84 | 85 | def should_wrap(self): 86 | ''' 87 | True if this class is actually needed. If false, then the output 88 | stream will not be affected, nor will win32 calls be issued, so 89 | wrapping stdout is not actually required. This will generally be 90 | False on non-Windows platforms, unless optional functionality like 91 | autoreset has been requested using kwargs to init() 92 | ''' 93 | return self.convert or self.strip or self.autoreset 94 | 95 | def get_win32_calls(self): 96 | if self.convert and winterm: 97 | return { 98 | AnsiStyle.RESET_ALL: (winterm.reset_all, ), 99 | AnsiStyle.BRIGHT: (winterm.style, WinStyle.BRIGHT), 100 | AnsiStyle.DIM: (winterm.style, WinStyle.NORMAL), 101 | AnsiStyle.NORMAL: (winterm.style, WinStyle.NORMAL), 102 | AnsiFore.BLACK: (winterm.fore, WinColor.BLACK), 103 | AnsiFore.RED: (winterm.fore, WinColor.RED), 104 | AnsiFore.GREEN: (winterm.fore, WinColor.GREEN), 105 | AnsiFore.YELLOW: (winterm.fore, WinColor.YELLOW), 106 | AnsiFore.BLUE: (winterm.fore, WinColor.BLUE), 107 | AnsiFore.MAGENTA: (winterm.fore, WinColor.MAGENTA), 108 | AnsiFore.CYAN: (winterm.fore, WinColor.CYAN), 109 | AnsiFore.WHITE: (winterm.fore, WinColor.GREY), 110 | AnsiFore.RESET: (winterm.fore, ), 111 | AnsiFore.LIGHTBLACK_EX: (winterm.fore, WinColor.BLACK, True), 112 | AnsiFore.LIGHTRED_EX: (winterm.fore, WinColor.RED, True), 113 | AnsiFore.LIGHTGREEN_EX: (winterm.fore, WinColor.GREEN, True), 114 | AnsiFore.LIGHTYELLOW_EX: (winterm.fore, WinColor.YELLOW, True), 115 | AnsiFore.LIGHTBLUE_EX: (winterm.fore, WinColor.BLUE, True), 116 | AnsiFore.LIGHTMAGENTA_EX: (winterm.fore, WinColor.MAGENTA, True), 117 | AnsiFore.LIGHTCYAN_EX: (winterm.fore, WinColor.CYAN, True), 118 | AnsiFore.LIGHTWHITE_EX: (winterm.fore, WinColor.GREY, True), 119 | AnsiBack.BLACK: (winterm.back, WinColor.BLACK), 120 | AnsiBack.RED: (winterm.back, WinColor.RED), 121 | AnsiBack.GREEN: (winterm.back, WinColor.GREEN), 122 | AnsiBack.YELLOW: (winterm.back, WinColor.YELLOW), 123 | AnsiBack.BLUE: (winterm.back, WinColor.BLUE), 124 | AnsiBack.MAGENTA: (winterm.back, WinColor.MAGENTA), 125 | AnsiBack.CYAN: (winterm.back, WinColor.CYAN), 126 | AnsiBack.WHITE: (winterm.back, WinColor.GREY), 127 | AnsiBack.RESET: (winterm.back, ), 128 | AnsiBack.LIGHTBLACK_EX: (winterm.back, WinColor.BLACK, True), 129 | AnsiBack.LIGHTRED_EX: (winterm.back, WinColor.RED, True), 130 | AnsiBack.LIGHTGREEN_EX: (winterm.back, WinColor.GREEN, True), 131 | AnsiBack.LIGHTYELLOW_EX: (winterm.back, WinColor.YELLOW, True), 132 | AnsiBack.LIGHTBLUE_EX: (winterm.back, WinColor.BLUE, True), 133 | AnsiBack.LIGHTMAGENTA_EX: (winterm.back, WinColor.MAGENTA, True), 134 | AnsiBack.LIGHTCYAN_EX: (winterm.back, WinColor.CYAN, True), 135 | AnsiBack.LIGHTWHITE_EX: (winterm.back, WinColor.GREY, True), 136 | } 137 | return dict() 138 | 139 | def write(self, text): 140 | if self.strip or self.convert: 141 | self.write_and_convert(text) 142 | else: 143 | self.wrapped.write(text) 144 | self.wrapped.flush() 145 | if self.autoreset: 146 | self.reset_all() 147 | 148 | 149 | def reset_all(self): 150 | if self.convert: 151 | self.call_win32('m', (0,)) 152 | elif not self.strip and not is_stream_closed(self.wrapped): 153 | self.wrapped.write(Style.RESET_ALL) 154 | 155 | 156 | def write_and_convert(self, text): 157 | ''' 158 | Write the given text to our wrapped stream, stripping any ANSI 159 | sequences from the text, and optionally converting them into win32 160 | calls. 161 | ''' 162 | cursor = 0 163 | text = self.convert_osc(text) 164 | for match in self.ANSI_CSI_RE.finditer(text): 165 | start, end = match.span() 166 | self.write_plain_text(text, cursor, start) 167 | self.convert_ansi(*match.groups()) 168 | cursor = end 169 | self.write_plain_text(text, cursor, len(text)) 170 | 171 | 172 | def write_plain_text(self, text, start, end): 173 | if start < end: 174 | self.wrapped.write(text[start:end]) 175 | self.wrapped.flush() 176 | 177 | 178 | def convert_ansi(self, paramstring, command): 179 | if self.convert: 180 | params = self.extract_params(command, paramstring) 181 | self.call_win32(command, params) 182 | 183 | 184 | def extract_params(self, command, paramstring): 185 | if command in 'Hf': 186 | params = tuple(int(p) if len(p) != 0 else 1 for p in paramstring.split(';')) 187 | while len(params) < 2: 188 | # defaults: 189 | params = params + (1,) 190 | else: 191 | params = tuple(int(p) for p in paramstring.split(';') if len(p) != 0) 192 | if len(params) == 0: 193 | # defaults: 194 | if command in 'JKm': 195 | params = (0,) 196 | elif command in 'ABCD': 197 | params = (1,) 198 | 199 | return params 200 | 201 | 202 | def call_win32(self, command, params): 203 | if command == 'm': 204 | for param in params: 205 | if param in self.win32_calls: 206 | func_args = self.win32_calls[param] 207 | func = func_args[0] 208 | args = func_args[1:] 209 | kwargs = dict(on_stderr=self.on_stderr) 210 | func(*args, **kwargs) 211 | elif command in 'J': 212 | winterm.erase_screen(params[0], on_stderr=self.on_stderr) 213 | elif command in 'K': 214 | winterm.erase_line(params[0], on_stderr=self.on_stderr) 215 | elif command in 'Hf': # cursor position - absolute 216 | winterm.set_cursor_position(params, on_stderr=self.on_stderr) 217 | elif command in 'ABCD': # cursor position - relative 218 | n = params[0] 219 | # A - up, B - down, C - forward, D - back 220 | x, y = {'A': (0, -n), 'B': (0, n), 'C': (n, 0), 'D': (-n, 0)}[command] 221 | winterm.cursor_adjust(x, y, on_stderr=self.on_stderr) 222 | 223 | 224 | def convert_osc(self, text): 225 | for match in self.ANSI_OSC_RE.finditer(text): 226 | start, end = match.span() 227 | text = text[:start] + text[end:] 228 | paramstring, command = match.groups() 229 | if command in '\x07': # \x07 = BEL 230 | params = paramstring.split(";") 231 | # 0 - change title and icon (we will only change title) 232 | # 1 - change icon (we don't support this) 233 | # 2 - change title 234 | if params[0] in '02': 235 | winterm.set_title(params[1]) 236 | return text 237 | -------------------------------------------------------------------------------- /requests_arcgis_auth/test/packages/colorama-0.3.9/colorama/initialise.py: -------------------------------------------------------------------------------- 1 | # Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. 2 | import atexit 3 | import contextlib 4 | import sys 5 | 6 | from .ansitowin32 import AnsiToWin32 7 | 8 | 9 | orig_stdout = None 10 | orig_stderr = None 11 | 12 | wrapped_stdout = None 13 | wrapped_stderr = None 14 | 15 | atexit_done = False 16 | 17 | 18 | def reset_all(): 19 | if AnsiToWin32 is not None: # Issue #74: objects might become None at exit 20 | AnsiToWin32(orig_stdout).reset_all() 21 | 22 | 23 | def init(autoreset=False, convert=None, strip=None, wrap=True): 24 | 25 | if not wrap and any([autoreset, convert, strip]): 26 | raise ValueError('wrap=False conflicts with any other arg=True') 27 | 28 | global wrapped_stdout, wrapped_stderr 29 | global orig_stdout, orig_stderr 30 | 31 | orig_stdout = sys.stdout 32 | orig_stderr = sys.stderr 33 | 34 | if sys.stdout is None: 35 | wrapped_stdout = None 36 | else: 37 | sys.stdout = wrapped_stdout = \ 38 | wrap_stream(orig_stdout, convert, strip, autoreset, wrap) 39 | if sys.stderr is None: 40 | wrapped_stderr = None 41 | else: 42 | sys.stderr = wrapped_stderr = \ 43 | wrap_stream(orig_stderr, convert, strip, autoreset, wrap) 44 | 45 | global atexit_done 46 | if not atexit_done: 47 | atexit.register(reset_all) 48 | atexit_done = True 49 | 50 | 51 | def deinit(): 52 | if orig_stdout is not None: 53 | sys.stdout = orig_stdout 54 | if orig_stderr is not None: 55 | sys.stderr = orig_stderr 56 | 57 | 58 | @contextlib.contextmanager 59 | def colorama_text(*args, **kwargs): 60 | init(*args, **kwargs) 61 | try: 62 | yield 63 | finally: 64 | deinit() 65 | 66 | 67 | def reinit(): 68 | if wrapped_stdout is not None: 69 | sys.stdout = wrapped_stdout 70 | if wrapped_stderr is not None: 71 | sys.stderr = wrapped_stderr 72 | 73 | 74 | def wrap_stream(stream, convert, strip, autoreset, wrap): 75 | if wrap: 76 | wrapper = AnsiToWin32(stream, 77 | convert=convert, strip=strip, autoreset=autoreset) 78 | if wrapper.should_wrap(): 79 | stream = wrapper.stream 80 | return stream 81 | 82 | 83 | -------------------------------------------------------------------------------- /requests_arcgis_auth/test/packages/colorama-0.3.9/colorama/win32.py: -------------------------------------------------------------------------------- 1 | # Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. 2 | 3 | # from winbase.h 4 | STDOUT = -11 5 | STDERR = -12 6 | 7 | try: 8 | import ctypes 9 | from ctypes import LibraryLoader 10 | windll = LibraryLoader(ctypes.WinDLL) 11 | from ctypes import wintypes 12 | except (AttributeError, ImportError): 13 | windll = None 14 | SetConsoleTextAttribute = lambda *_: None 15 | winapi_test = lambda *_: None 16 | else: 17 | from ctypes import byref, Structure, c_char, POINTER 18 | 19 | COORD = wintypes._COORD 20 | 21 | class CONSOLE_SCREEN_BUFFER_INFO(Structure): 22 | """struct in wincon.h.""" 23 | _fields_ = [ 24 | ("dwSize", COORD), 25 | ("dwCursorPosition", COORD), 26 | ("wAttributes", wintypes.WORD), 27 | ("srWindow", wintypes.SMALL_RECT), 28 | ("dwMaximumWindowSize", COORD), 29 | ] 30 | def __str__(self): 31 | return '(%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d)' % ( 32 | self.dwSize.Y, self.dwSize.X 33 | , self.dwCursorPosition.Y, self.dwCursorPosition.X 34 | , self.wAttributes 35 | , self.srWindow.Top, self.srWindow.Left, self.srWindow.Bottom, self.srWindow.Right 36 | , self.dwMaximumWindowSize.Y, self.dwMaximumWindowSize.X 37 | ) 38 | 39 | _GetStdHandle = windll.kernel32.GetStdHandle 40 | _GetStdHandle.argtypes = [ 41 | wintypes.DWORD, 42 | ] 43 | _GetStdHandle.restype = wintypes.HANDLE 44 | 45 | _GetConsoleScreenBufferInfo = windll.kernel32.GetConsoleScreenBufferInfo 46 | _GetConsoleScreenBufferInfo.argtypes = [ 47 | wintypes.HANDLE, 48 | POINTER(CONSOLE_SCREEN_BUFFER_INFO), 49 | ] 50 | _GetConsoleScreenBufferInfo.restype = wintypes.BOOL 51 | 52 | _SetConsoleTextAttribute = windll.kernel32.SetConsoleTextAttribute 53 | _SetConsoleTextAttribute.argtypes = [ 54 | wintypes.HANDLE, 55 | wintypes.WORD, 56 | ] 57 | _SetConsoleTextAttribute.restype = wintypes.BOOL 58 | 59 | _SetConsoleCursorPosition = windll.kernel32.SetConsoleCursorPosition 60 | _SetConsoleCursorPosition.argtypes = [ 61 | wintypes.HANDLE, 62 | COORD, 63 | ] 64 | _SetConsoleCursorPosition.restype = wintypes.BOOL 65 | 66 | _FillConsoleOutputCharacterA = windll.kernel32.FillConsoleOutputCharacterA 67 | _FillConsoleOutputCharacterA.argtypes = [ 68 | wintypes.HANDLE, 69 | c_char, 70 | wintypes.DWORD, 71 | COORD, 72 | POINTER(wintypes.DWORD), 73 | ] 74 | _FillConsoleOutputCharacterA.restype = wintypes.BOOL 75 | 76 | _FillConsoleOutputAttribute = windll.kernel32.FillConsoleOutputAttribute 77 | _FillConsoleOutputAttribute.argtypes = [ 78 | wintypes.HANDLE, 79 | wintypes.WORD, 80 | wintypes.DWORD, 81 | COORD, 82 | POINTER(wintypes.DWORD), 83 | ] 84 | _FillConsoleOutputAttribute.restype = wintypes.BOOL 85 | 86 | _SetConsoleTitleW = windll.kernel32.SetConsoleTitleW 87 | _SetConsoleTitleW.argtypes = [ 88 | wintypes.LPCWSTR 89 | ] 90 | _SetConsoleTitleW.restype = wintypes.BOOL 91 | 92 | handles = { 93 | STDOUT: _GetStdHandle(STDOUT), 94 | STDERR: _GetStdHandle(STDERR), 95 | } 96 | 97 | def _winapi_test(handle): 98 | csbi = CONSOLE_SCREEN_BUFFER_INFO() 99 | success = _GetConsoleScreenBufferInfo( 100 | handle, byref(csbi)) 101 | return bool(success) 102 | 103 | def winapi_test(): 104 | return any(_winapi_test(h) for h in handles.values()) 105 | 106 | def GetConsoleScreenBufferInfo(stream_id=STDOUT): 107 | handle = handles[stream_id] 108 | csbi = CONSOLE_SCREEN_BUFFER_INFO() 109 | success = _GetConsoleScreenBufferInfo( 110 | handle, byref(csbi)) 111 | return csbi 112 | 113 | def SetConsoleTextAttribute(stream_id, attrs): 114 | handle = handles[stream_id] 115 | return _SetConsoleTextAttribute(handle, attrs) 116 | 117 | def SetConsoleCursorPosition(stream_id, position, adjust=True): 118 | position = COORD(*position) 119 | # If the position is out of range, do nothing. 120 | if position.Y <= 0 or position.X <= 0: 121 | return 122 | # Adjust for Windows' SetConsoleCursorPosition: 123 | # 1. being 0-based, while ANSI is 1-based. 124 | # 2. expecting (x,y), while ANSI uses (y,x). 125 | adjusted_position = COORD(position.Y - 1, position.X - 1) 126 | if adjust: 127 | # Adjust for viewport's scroll position 128 | sr = GetConsoleScreenBufferInfo(STDOUT).srWindow 129 | adjusted_position.Y += sr.Top 130 | adjusted_position.X += sr.Left 131 | # Resume normal processing 132 | handle = handles[stream_id] 133 | return _SetConsoleCursorPosition(handle, adjusted_position) 134 | 135 | def FillConsoleOutputCharacter(stream_id, char, length, start): 136 | handle = handles[stream_id] 137 | char = c_char(char.encode()) 138 | length = wintypes.DWORD(length) 139 | num_written = wintypes.DWORD(0) 140 | # Note that this is hard-coded for ANSI (vs wide) bytes. 141 | success = _FillConsoleOutputCharacterA( 142 | handle, char, length, start, byref(num_written)) 143 | return num_written.value 144 | 145 | def FillConsoleOutputAttribute(stream_id, attr, length, start): 146 | ''' FillConsoleOutputAttribute( hConsole, csbi.wAttributes, dwConSize, coordScreen, &cCharsWritten )''' 147 | handle = handles[stream_id] 148 | attribute = wintypes.WORD(attr) 149 | length = wintypes.DWORD(length) 150 | num_written = wintypes.DWORD(0) 151 | # Note that this is hard-coded for ANSI (vs wide) bytes. 152 | return _FillConsoleOutputAttribute( 153 | handle, attribute, length, start, byref(num_written)) 154 | 155 | def SetConsoleTitle(title): 156 | return _SetConsoleTitleW(title) 157 | -------------------------------------------------------------------------------- /requests_arcgis_auth/test/packages/colorama-0.3.9/colorama/winterm.py: -------------------------------------------------------------------------------- 1 | # Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. 2 | from . import win32 3 | 4 | 5 | # from wincon.h 6 | class WinColor(object): 7 | BLACK = 0 8 | BLUE = 1 9 | GREEN = 2 10 | CYAN = 3 11 | RED = 4 12 | MAGENTA = 5 13 | YELLOW = 6 14 | GREY = 7 15 | 16 | # from wincon.h 17 | class WinStyle(object): 18 | NORMAL = 0x00 # dim text, dim background 19 | BRIGHT = 0x08 # bright text, dim background 20 | BRIGHT_BACKGROUND = 0x80 # dim text, bright background 21 | 22 | class WinTerm(object): 23 | 24 | def __init__(self): 25 | self._default = win32.GetConsoleScreenBufferInfo(win32.STDOUT).wAttributes 26 | self.set_attrs(self._default) 27 | self._default_fore = self._fore 28 | self._default_back = self._back 29 | self._default_style = self._style 30 | # In order to emulate LIGHT_EX in windows, we borrow the BRIGHT style. 31 | # So that LIGHT_EX colors and BRIGHT style do not clobber each other, 32 | # we track them separately, since LIGHT_EX is overwritten by Fore/Back 33 | # and BRIGHT is overwritten by Style codes. 34 | self._light = 0 35 | 36 | def get_attrs(self): 37 | return self._fore + self._back * 16 + (self._style | self._light) 38 | 39 | def set_attrs(self, value): 40 | self._fore = value & 7 41 | self._back = (value >> 4) & 7 42 | self._style = value & (WinStyle.BRIGHT | WinStyle.BRIGHT_BACKGROUND) 43 | 44 | def reset_all(self, on_stderr=None): 45 | self.set_attrs(self._default) 46 | self.set_console(attrs=self._default) 47 | 48 | def fore(self, fore=None, light=False, on_stderr=False): 49 | if fore is None: 50 | fore = self._default_fore 51 | self._fore = fore 52 | # Emulate LIGHT_EX with BRIGHT Style 53 | if light: 54 | self._light |= WinStyle.BRIGHT 55 | else: 56 | self._light &= ~WinStyle.BRIGHT 57 | self.set_console(on_stderr=on_stderr) 58 | 59 | def back(self, back=None, light=False, on_stderr=False): 60 | if back is None: 61 | back = self._default_back 62 | self._back = back 63 | # Emulate LIGHT_EX with BRIGHT_BACKGROUND Style 64 | if light: 65 | self._light |= WinStyle.BRIGHT_BACKGROUND 66 | else: 67 | self._light &= ~WinStyle.BRIGHT_BACKGROUND 68 | self.set_console(on_stderr=on_stderr) 69 | 70 | def style(self, style=None, on_stderr=False): 71 | if style is None: 72 | style = self._default_style 73 | self._style = style 74 | self.set_console(on_stderr=on_stderr) 75 | 76 | def set_console(self, attrs=None, on_stderr=False): 77 | if attrs is None: 78 | attrs = self.get_attrs() 79 | handle = win32.STDOUT 80 | if on_stderr: 81 | handle = win32.STDERR 82 | win32.SetConsoleTextAttribute(handle, attrs) 83 | 84 | def get_position(self, handle): 85 | position = win32.GetConsoleScreenBufferInfo(handle).dwCursorPosition 86 | # Because Windows coordinates are 0-based, 87 | # and win32.SetConsoleCursorPosition expects 1-based. 88 | position.X += 1 89 | position.Y += 1 90 | return position 91 | 92 | def set_cursor_position(self, position=None, on_stderr=False): 93 | if position is None: 94 | # I'm not currently tracking the position, so there is no default. 95 | # position = self.get_position() 96 | return 97 | handle = win32.STDOUT 98 | if on_stderr: 99 | handle = win32.STDERR 100 | win32.SetConsoleCursorPosition(handle, position) 101 | 102 | def cursor_adjust(self, x, y, on_stderr=False): 103 | handle = win32.STDOUT 104 | if on_stderr: 105 | handle = win32.STDERR 106 | position = self.get_position(handle) 107 | adjusted_position = (position.Y + y, position.X + x) 108 | win32.SetConsoleCursorPosition(handle, adjusted_position, adjust=False) 109 | 110 | def erase_screen(self, mode=0, on_stderr=False): 111 | # 0 should clear from the cursor to the end of the screen. 112 | # 1 should clear from the cursor to the beginning of the screen. 113 | # 2 should clear the entire screen, and move cursor to (1,1) 114 | handle = win32.STDOUT 115 | if on_stderr: 116 | handle = win32.STDERR 117 | csbi = win32.GetConsoleScreenBufferInfo(handle) 118 | # get the number of character cells in the current buffer 119 | cells_in_screen = csbi.dwSize.X * csbi.dwSize.Y 120 | # get number of character cells before current cursor position 121 | cells_before_cursor = csbi.dwSize.X * csbi.dwCursorPosition.Y + csbi.dwCursorPosition.X 122 | if mode == 0: 123 | from_coord = csbi.dwCursorPosition 124 | cells_to_erase = cells_in_screen - cells_before_cursor 125 | if mode == 1: 126 | from_coord = win32.COORD(0, 0) 127 | cells_to_erase = cells_before_cursor 128 | elif mode == 2: 129 | from_coord = win32.COORD(0, 0) 130 | cells_to_erase = cells_in_screen 131 | # fill the entire screen with blanks 132 | win32.FillConsoleOutputCharacter(handle, ' ', cells_to_erase, from_coord) 133 | # now set the buffer's attributes accordingly 134 | win32.FillConsoleOutputAttribute(handle, self.get_attrs(), cells_to_erase, from_coord) 135 | if mode == 2: 136 | # put the cursor where needed 137 | win32.SetConsoleCursorPosition(handle, (1, 1)) 138 | 139 | def erase_line(self, mode=0, on_stderr=False): 140 | # 0 should clear from the cursor to the end of the line. 141 | # 1 should clear from the cursor to the beginning of the line. 142 | # 2 should clear the entire line. 143 | handle = win32.STDOUT 144 | if on_stderr: 145 | handle = win32.STDERR 146 | csbi = win32.GetConsoleScreenBufferInfo(handle) 147 | if mode == 0: 148 | from_coord = csbi.dwCursorPosition 149 | cells_to_erase = csbi.dwSize.X - csbi.dwCursorPosition.X 150 | if mode == 1: 151 | from_coord = win32.COORD(0, csbi.dwCursorPosition.Y) 152 | cells_to_erase = csbi.dwCursorPosition.X 153 | elif mode == 2: 154 | from_coord = win32.COORD(0, csbi.dwCursorPosition.Y) 155 | cells_to_erase = csbi.dwSize.X 156 | # fill the entire screen with blanks 157 | win32.FillConsoleOutputCharacter(handle, ' ', cells_to_erase, from_coord) 158 | # now set the buffer's attributes accordingly 159 | win32.FillConsoleOutputAttribute(handle, self.get_attrs(), cells_to_erase, from_coord) 160 | 161 | def set_title(self, title): 162 | win32.SetConsoleTitle(title) 163 | -------------------------------------------------------------------------------- /requests_arcgis_auth/test/packages/colorama-0.3.9/demos/demo.bat: -------------------------------------------------------------------------------- 1 | :: Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. 2 | 3 | :: Script to demonstrate features of colorama. 4 | 5 | :: This demo is also used to verify correctness visually, because we don't 6 | :: have automated tests. 7 | 8 | :: Implemented as a bash script which invokes python so that we can test the 9 | :: behaviour on exit, which resets default colors again. 10 | 11 | :: print grid of all colors and brightnesses 12 | python demo01.py 13 | 14 | :: Simple demo of changing foreground, background and brightness. 15 | python demo02.py 16 | 17 | :: Demonstrate the different behavior when autoreset is True and False. 18 | python demo03.py 19 | 20 | :: check that stripped ANSI in redirected stderr does not affect stdout 21 | if exist demo04.out del demo04.out 22 | python demo04.py 2> demo04.out 23 | type demo04.out 24 | 25 | :: Demonstrate the difference between colorama intialized with wrapping on and off. 26 | python demo05.py 27 | 28 | :: # Demonstrate printing colored, random characters at random positions on the screen 29 | python demo06.py 30 | 31 | :: demo07.py not shown 32 | :: Demonstrate cursor relative movement: UP, DOWN, FORWARD, and BACK in colorama.CURSOR 33 | -------------------------------------------------------------------------------- /requests_arcgis_auth/test/packages/colorama-0.3.9/demos/demo.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. 3 | 4 | # Script to demonstrate features of colorama. 5 | 6 | # This demo is also used to verify correctness visually, because we don't have 7 | # automated tests. 8 | 9 | # Implemented as a bash script which invokes python so that we can test the 10 | # behaviour on exit, which resets default colors again. 11 | 12 | # print grid of all colors and brightnesses 13 | python demo01.py 14 | 15 | # Simple demo of changing foreground, background and brightness. 16 | python demo02.py 17 | 18 | # Demonstrate the different behavior when autoreset is True and False. 19 | python demo03.py 20 | 21 | # check that stripped ANSI in redirected stderr does not affect stdout 22 | rm -f demo04.out 23 | python demo04.py 2> demo04.out 24 | cat demo04.out 25 | 26 | # Demonstrate the difference between colorama intialized with wrapping on and off. 27 | python demo05.py 28 | 29 | # Demonstrate printing colored, random characters at random positions on the screen 30 | python demo06.py 31 | 32 | # demo07.py not shown 33 | # Demonstrate cursor relative movement: UP, DOWN, FORWARD, and BACK in colorama.CURSOR 34 | 35 | #Demonstrate the use of a context manager instead of manually using init and deinit 36 | python demo08.py 37 | -------------------------------------------------------------------------------- /requests_arcgis_auth/test/packages/colorama-0.3.9/demos/demo01.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. 3 | 4 | # print grid of all colors and brightnesses 5 | # uses stdout.write to write chars with no newline nor spaces between them 6 | # This should run more-or-less identically on Windows and Unix. 7 | from __future__ import print_function 8 | import sys 9 | 10 | # Add parent dir to sys path, so the following 'import colorama' always finds 11 | # the local source in preference to any installed version of colorama. 12 | import fixpath 13 | from colorama import init, Fore, Back, Style 14 | 15 | init() 16 | 17 | # Fore, Back and Style are convenience classes for the constant ANSI strings that set 18 | # the foreground, background and style. The don't have any magic of their own. 19 | FORES = [ Fore.BLACK, Fore.RED, Fore.GREEN, Fore.YELLOW, Fore.BLUE, Fore.MAGENTA, Fore.CYAN, Fore.WHITE ] 20 | BACKS = [ Back.BLACK, Back.RED, Back.GREEN, Back.YELLOW, Back.BLUE, Back.MAGENTA, Back.CYAN, Back.WHITE ] 21 | STYLES = [ Style.DIM, Style.NORMAL, Style.BRIGHT ] 22 | 23 | NAMES = { 24 | Fore.BLACK: 'black', Fore.RED: 'red', Fore.GREEN: 'green', Fore.YELLOW: 'yellow', Fore.BLUE: 'blue', Fore.MAGENTA: 'magenta', Fore.CYAN: 'cyan', Fore.WHITE: 'white' 25 | , Fore.RESET: 'reset', 26 | Back.BLACK: 'black', Back.RED: 'red', Back.GREEN: 'green', Back.YELLOW: 'yellow', Back.BLUE: 'blue', Back.MAGENTA: 'magenta', Back.CYAN: 'cyan', Back.WHITE: 'white', 27 | Back.RESET: 'reset' 28 | } 29 | 30 | # show the color names 31 | sys.stdout.write(' ') 32 | for foreground in FORES: 33 | sys.stdout.write('%s%-7s' % (foreground, NAMES[foreground])) 34 | print() 35 | 36 | # make a row for each background color 37 | for background in BACKS: 38 | sys.stdout.write('%s%-7s%s %s' % (background, NAMES[background], Back.RESET, background)) 39 | # make a column for each foreground color 40 | for foreground in FORES: 41 | sys.stdout.write(foreground) 42 | # show dim, normal bright 43 | for brightness in STYLES: 44 | sys.stdout.write('%sX ' % brightness) 45 | sys.stdout.write(Style.RESET_ALL + ' ' + background) 46 | print(Style.RESET_ALL) 47 | 48 | print() 49 | -------------------------------------------------------------------------------- /requests_arcgis_auth/test/packages/colorama-0.3.9/demos/demo02.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. 3 | 4 | # Simple demo of changing foreground, background and brightness. 5 | 6 | from __future__ import print_function 7 | import fixpath 8 | from colorama import init, Fore, Back, Style 9 | 10 | init() 11 | 12 | print(Fore.GREEN + 'green, ' 13 | + Fore.RED + 'red, ' 14 | + Fore.RESET + 'normal, ' 15 | , end='') 16 | print(Back.GREEN + 'green, ' 17 | + Back.RED + 'red, ' 18 | + Back.RESET + 'normal, ' 19 | , end='') 20 | print(Style.DIM + 'dim, ' 21 | + Style.BRIGHT + 'bright, ' 22 | + Style.NORMAL + 'normal' 23 | , end=' ') 24 | print() 25 | 26 | -------------------------------------------------------------------------------- /requests_arcgis_auth/test/packages/colorama-0.3.9/demos/demo03.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. 3 | 4 | # Demonstrate the different behavior when autoreset is True and False. 5 | 6 | from __future__ import print_function 7 | import fixpath 8 | from colorama import init, Fore, Back, Style 9 | 10 | init(autoreset=True) 11 | print(Fore.CYAN + Back.MAGENTA + Style.BRIGHT + 'Line 1: colored, with autoreset=True') 12 | print('Line 2: When auto reset is True, the color settings need to be set with every print.') 13 | 14 | init(autoreset=False) 15 | print(Fore.YELLOW + Back.BLUE + Style.BRIGHT + 'Line 3: colored, with autoreset=False') 16 | print('Line 4: When autoreset=False, the prior color settings linger (this is the default behavior).') 17 | -------------------------------------------------------------------------------- /requests_arcgis_auth/test/packages/colorama-0.3.9/demos/demo04.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. 3 | 4 | # check that stripped ANSI in redirected stderr does not affect stdout 5 | from __future__ import print_function 6 | import sys 7 | import fixpath 8 | from colorama import init, Fore 9 | 10 | init() 11 | print(Fore.GREEN + 'GREEN set on stdout. ', end='') 12 | print(Fore.RED + 'RED redirected stderr', file=sys.stderr) 13 | print('Further stdout should be GREEN, i.e., the stderr redirection should not affect stdout.') 14 | -------------------------------------------------------------------------------- /requests_arcgis_auth/test/packages/colorama-0.3.9/demos/demo05.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. 3 | 4 | # Demonstrate the difference between colorama intialized with wrapping on and off. 5 | # The point of the demonstration is to show how the ANSI wrapping on Windows can be disabled. 6 | # The unwrapped cases will be interpreted with ANSI on Unix, but not on Windows. 7 | 8 | from __future__ import print_function 9 | import sys 10 | import fixpath 11 | from colorama import AnsiToWin32, init, Fore 12 | 13 | init() 14 | print('%sWrapped yellow going to stdout, via the default print function.' % Fore.YELLOW) 15 | 16 | init(wrap=False) 17 | print('%sUnwrapped CYAN going to stdout, via the default print function.' % Fore.CYAN) 18 | print('%sUnwrapped CYAN, using the file parameter to write via colorama the AnsiToWin32 function.' % Fore.CYAN, file=AnsiToWin32(sys.stdout)) 19 | print('%sUnwrapped RED going to stdout, via the default print function.' % Fore.RED) 20 | 21 | init() 22 | print('%sWrapped RED going to stdout, via the default print function.' % Fore.RED) 23 | -------------------------------------------------------------------------------- /requests_arcgis_auth/test/packages/colorama-0.3.9/demos/demo06.py: -------------------------------------------------------------------------------- 1 | # Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. 2 | from __future__ import print_function 3 | import fixpath 4 | import colorama 5 | from colorama import Fore, Back, Style 6 | from random import randint, choice 7 | from string import printable 8 | 9 | # Demonstrate printing colored, random characters at random positions on the screen 10 | 11 | # Fore, Back and Style are convenience classes for the constant ANSI strings that set 12 | # the foreground, background and style. The don't have any magic of their own. 13 | FORES = [ Fore.BLACK, Fore.RED, Fore.GREEN, Fore.YELLOW, Fore.BLUE, Fore.MAGENTA, Fore.CYAN, Fore.WHITE ] 14 | BACKS = [ Back.BLACK, Back.RED, Back.GREEN, Back.YELLOW, Back.BLUE, Back.MAGENTA, Back.CYAN, Back.WHITE ] 15 | STYLES = [ Style.DIM, Style.NORMAL, Style.BRIGHT ] 16 | 17 | # This assumes your terminal is 80x24. Ansi minimum coordinate is (1,1). 18 | MINY, MAXY = 1, 24 19 | MINX, MAXX = 1, 80 20 | 21 | # set of printable ASCII characters, including a space. 22 | CHARS = ' ' + printable.strip() 23 | 24 | PASSES = 1000 25 | 26 | def main(): 27 | colorama.init() 28 | # gratuitous use of lambda. 29 | pos = lambda y, x: '\x1b[%d;%dH' % (y, x) 30 | # draw a white border. 31 | print(Back.WHITE, end='') 32 | print('%s%s' % (pos(MINY, MINX), ' '*MAXX), end='') 33 | for y in range(MINY, 1+MAXY): 34 | print('%s %s ' % (pos(y, MINX), pos(y, MAXX)), end='') 35 | print('%s%s' % (pos(MAXY, MINX), ' '*MAXX), end='') 36 | # draw some blinky lights for a while. 37 | for i in range(PASSES): 38 | print('%s%s%s%s%s' % (pos(randint(1+MINY,MAXY-1), randint(1+MINX,MAXX-1)), choice(FORES), choice(BACKS), choice(STYLES), choice(CHARS)), end='') 39 | # put cursor to top, left, and set color to white-on-black with normal brightness. 40 | print('%s%s%s%s' % (pos(MINY, MINX), Fore.WHITE, Back.BLACK, Style.NORMAL), end='') 41 | 42 | if __name__ == '__main__': 43 | main() 44 | -------------------------------------------------------------------------------- /requests_arcgis_auth/test/packages/colorama-0.3.9/demos/demo07.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | import fixpath 3 | import colorama 4 | 5 | # Demonstrate cursor relative movement: UP, DOWN, FORWARD, and BACK in colorama.CURSOR 6 | 7 | up = colorama.Cursor.UP 8 | down = colorama.Cursor.DOWN 9 | forward = colorama.Cursor.FORWARD 10 | back = colorama.Cursor.BACK 11 | 12 | def main(): 13 | """ 14 | expected output: 15 | 1a2 16 | aba 17 | 3a4 18 | """ 19 | colorama.init() 20 | print("aaa") 21 | print("aaa") 22 | print("aaa") 23 | print(forward() + up(2) + "b" + up() + back(2) + "1" + forward() + "2" + back(3) + down(2) + "3" + forward() + "4") 24 | 25 | 26 | if __name__ == '__main__': 27 | main() 28 | -------------------------------------------------------------------------------- /requests_arcgis_auth/test/packages/colorama-0.3.9/demos/demo08.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | import fixpath 3 | from colorama import colorama_text, Fore 4 | 5 | 6 | def main(): 7 | """automatically reset stdout""" 8 | with colorama_text(): 9 | print(Fore.GREEN + 'text is green') 10 | print(Fore.RESET + 'text is back to normal') 11 | 12 | print('text is back to stdout') 13 | 14 | if __name__ == '__main__': 15 | main() 16 | -------------------------------------------------------------------------------- /requests_arcgis_auth/test/packages/colorama-0.3.9/demos/fixpath.py: -------------------------------------------------------------------------------- 1 | # Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. 2 | 3 | # Add demo dir's parent to sys path, so that 'import colorama' always finds 4 | # the local source in preference to any installed version of colorama. 5 | import sys 6 | from os.path import normpath, dirname, join 7 | local_colorama_module = normpath(join(dirname(__file__), '..')) 8 | sys.path.insert(0, local_colorama_module) 9 | 10 | -------------------------------------------------------------------------------- /requests_arcgis_auth/test/packages/colorama-0.3.9/setup.cfg: -------------------------------------------------------------------------------- 1 | [bdist_wheel] 2 | universal = 1 3 | 4 | [egg_info] 5 | tag_build = 6 | tag_date = 0 7 | tag_svn_revision = 0 8 | 9 | -------------------------------------------------------------------------------- /requests_arcgis_auth/test/packages/colorama-0.3.9/setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. 3 | 4 | from __future__ import with_statement 5 | 6 | import os 7 | import re 8 | try: 9 | from setuptools import setup 10 | except ImportError: 11 | from distutils.core import setup 12 | 13 | 14 | NAME = 'colorama' 15 | 16 | 17 | def get_long_description(filename): 18 | readme = os.path.join(os.path.dirname(__file__), filename) 19 | with open(readme) as fp: 20 | return fp.read() 21 | 22 | def read_file(path): 23 | with open(os.path.join(os.path.dirname(__file__), path)) as fp: 24 | return fp.read() 25 | 26 | def _get_version_match(content): 27 | # Search for lines of the form: # __version__ = 'ver' 28 | regex = r"^__version__ = ['\"]([^'\"]*)['\"]" 29 | version_match = re.search(regex, content, re.M) 30 | if version_match: 31 | return version_match.group(1) 32 | raise RuntimeError("Unable to find version string.") 33 | 34 | def get_version(path): 35 | return _get_version_match(read_file(path)) 36 | 37 | setup( 38 | name=NAME, 39 | version=get_version(os.path.join('colorama', '__init__.py')), 40 | description='Cross-platform colored terminal text.', 41 | long_description=read_file('README.rst'), 42 | keywords='color colour terminal text ansi windows crossplatform xplatform', 43 | author='Jonathan Hartley', 44 | author_email='tartley@tartley.com', 45 | maintainer='Arnon Yaari', 46 | url='https://github.com/tartley/colorama', 47 | license='BSD', 48 | packages=[NAME], 49 | # see classifiers http://pypi.python.org/pypi?%3Aaction=list_classifiers 50 | classifiers=[ 51 | 'Development Status :: 5 - Production/Stable', 52 | 'Environment :: Console', 53 | 'Intended Audience :: Developers', 54 | 'License :: OSI Approved :: BSD License', 55 | 'Operating System :: OS Independent', 56 | 'Programming Language :: Python :: 2', 57 | 'Programming Language :: Python :: 2.5', 58 | 'Programming Language :: Python :: 2.6', 59 | 'Programming Language :: Python :: 2.7', 60 | 'Programming Language :: Python :: 3', 61 | 'Programming Language :: Python :: 3.1', 62 | 'Programming Language :: Python :: 3.2', 63 | 'Programming Language :: Python :: 3.3', 64 | 'Programming Language :: Python :: 3.4', 65 | 'Programming Language :: Python :: 3.5', 66 | 'Topic :: Terminals', 67 | ] 68 | ) 69 | 70 | -------------------------------------------------------------------------------- /requests_arcgis_auth/test/test.cfg: -------------------------------------------------------------------------------- 1 | 2 | [General Settings] 3 | verify_certs = False 4 | 5 | # URL's with different security postures. Passwords will be prompted (except for 'duplicate' usernames, the previous password promt will be re-used) 6 | [ArcGIS Server Token Auth] 7 | url = https://gis.dev.blm.doi.net/arcgispub/admin/?f=json 8 | expected_output = {"resources":["machines","clusters","system","services","security","data","uploads","logs","mode","usagereports"],"currentVersion":10.41,"fullVersion":"10.4.1","acceptLanguage":null} 9 | auth_handler = ArcGISServerAuth 10 | username = blm\pfoppe 11 | 12 | [ArcGIS Server Kerberos Auth] 13 | url = https://gis.dev.blm.doi.net/arcgisauthpub/admin/?f=json 14 | expected_output={"isServerLicensed":"true","resources":["machines","clusters","system","services","security","data","uploads","logs","mode","usagereports"],"currentVersion":10.61,"fullVersion":"10.6.1","acceptLanguage":null} 15 | auth_handler = ArcGISServerAuth 16 | 17 | [ArcGIS Server NTLM Auth] 18 | url = https://gis.blm.doi.net/arcgisauthpub/admin/?f=json 19 | username = blm\pfoppe 20 | expected_output={"resources":["machines","clusters","system","services","security","data","uploads","logs","mode","usagereports"],"currentVersion":10.41,"fullVersion":"10.4.1","acceptLanguage":null} 21 | auth_handler = ArcGISServerAuth 22 | 23 | [Portal Token Auth] 24 | url = https://blm-egis.maps.arcgis.com/sharing/rest/portals/self/servers?f=json 25 | username = pfoppe_BLM 26 | expected_output = {"servers":[]} 27 | auth_handler = ArcGISPortalAuth 28 | 29 | [Portal Kerberos Auth] 30 | url = https://ilmocop3ap60.blm.doi.net/portal/sharing/rest?f=json 31 | expected_output = {"currentVersion":"5.1"} 32 | auth_handler = ArcGISPortalAuth 33 | 34 | [Portal NTLM Auth] 35 | url = https://egisportal.blm.doi.net/portal/sharing/rest?f=json 36 | username = blm\pfoppe 37 | expected_output = {"currentVersion":"5.1"} 38 | auth_handler = ArcGISPortalAuth 39 | 40 | [Portal SAML Auth] 41 | url = https://blm-egis.maps.arcgis.com/sharing/rest/portals/self/servers?f=json 42 | expected_output = {"servers":[]} 43 | auth_handler = ArcGISPortalSAMLAuth 44 | client_id = oeBg9SpWt0NPByQb 45 | 46 | 47 | [FWS Portal SAML Auth] 48 | url = https://fws.maps.arcgis.com/sharing/rest/portals/self/servers?f=json 49 | expected_output = {"servers":[]} 50 | auth_handler = ArcGISPortalSAMLAuth 51 | client_id = 3YzfqWX0IyCY5rBf -------------------------------------------------------------------------------- /requests_arcgis_auth/test/test_arcgis_auth.py: -------------------------------------------------------------------------------- 1 | 2 | import sys,os 3 | import ConfigParser 4 | import requests 5 | from getpass import getpass 6 | 7 | import warnings 8 | warnings.filterwarnings("ignore") 9 | print ("ATTN!!! Warnings are being filtered !!!") 10 | 11 | if __name__ == '__main__' and __package__ is None: 12 | sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) 13 | from arcgis_token_auth import ArcGISServerTokenAuth, ArcGISPortalTokenAuth 14 | from arcgis_auth import ArcGISPortalAuth, ArcGISServerAuth 15 | from arcgis_saml_auth import ArcGISPortalSAMLAuth 16 | 17 | try: 18 | from colorama import init 19 | init(autoreset=True) 20 | except: 21 | sys.path.append(os.path.join(os.getcwd(),"packages","colorama-0.3.9")) 22 | from colorama import init 23 | init(autoreset=True) 24 | 25 | from colorama import Fore,Back 26 | 27 | def print_color(color,*objs): 28 | # color = foreground colors from colorama.Fore. EX: Fore.GREEN 29 | # *objs = Objects to print that color 30 | print (color+" ".join([str(x) for x in objs])) 31 | 32 | def print_green(*objs): 33 | #print (Fore.GREEN+" ".join([str(x) for x in objs])) 34 | print_color(Fore.GREEN,*objs) 35 | 36 | def print_red(*objs): 37 | print_color(Fore.RED,*objs) 38 | 39 | def print_yellow(*objs): 40 | print_color(Fore.YELLOW,*objs) 41 | 42 | def print_cyan(*objs): 43 | print_color(Fore.CYAN,*objs) 44 | 45 | 46 | TOOL_INFO = """ 47 | This test harness will execute HTTP requests to Esri ArcGIS for Server and Portal (including ArcGIS Online) 48 | using custom authenticaiton handlers for the python requests API. 49 | 50 | Optional Input - 51 | CONFIG_FILE (defaults to test.cfg). 52 | 53 | Usage: 54 | python.exe test_arcgis_auth.py 55 | """ 56 | 57 | SAMPLE_CONFIG_FILE = """ 58 | [General Settings] 59 | verify_certs = False 60 | 61 | # URL's with different security postures. Passwords will be prompted (except for 'duplicate' usernames, the previous password promt will be re-used) 62 | [ArcGIS Server Token Auth] 63 | url = https://gis.dev.blm.doi.net/arcgispub/admin/?f=json 64 | expected_output = {"resources":["machines","clusters","system","services","security","data","uploads","logs","mode","usagereports"],"currentVersion":10.41,"fullVersion":"10.4.1","acceptLanguage":null} 65 | auth_handler = ArcGISServerTokenAuth 66 | username = blm\pfoppe 67 | 68 | [ArcGIS Server Kerberos Auth] 69 | url = https://gis.dev.blm.doi.net/arcgisauthpub/admin/?f=json 70 | expected_output={"resources":["machines","clusters","system","services","security","data","uploads","logs","mode","usagereports"],"currentVersion":10.41,"fullVersion":"10.4.1","acceptLanguage":null} 71 | auth_handler = ArcGISServerAuth 72 | 73 | [ArcGIS Server NTLM Auth] 74 | url = https://gis.blm.doi.net/arcgisauthpub/admin/?f=json 75 | username = blm\pfoppe 76 | expected_output={"resources":["machines","clusters","system","services","security","data","uploads","logs","mode","usagereports"],"currentVersion":10.41,"fullVersion":"10.4.1","acceptLanguage":null} 77 | auth_handler = ArcGISServerAuth 78 | 79 | [Portal Token Auth] 80 | url = https://blm-egis.maps.arcgis.com/sharing/rest?f=json 81 | username = pfoppe_BLM 82 | expected_output = {"currentVersion":"5.1"} 83 | auth_handler = ArcGISPortalTokenAuth 84 | 85 | [Portal Kerberos Auth] 86 | url = https://ilmocop3ap60.blm.doi.net/portal/sharing/rest?f=json 87 | expected_output = {"currentVersion":"3.10"} 88 | auth_handler = ArcGISPortalAuth 89 | 90 | [Portal NTLM Auth] 91 | url = https://egisportal.blm.doi.net/portal/sharing/rest?f=json 92 | username = blm\pfoppe 93 | expected_output = {"currentVersion":"3.10"} 94 | auth_handler = ArcGISPortalAuth 95 | \n\n\n""" 96 | 97 | 98 | def get_inputs(): 99 | if len(sys.argv) == 2: 100 | cfg_file = sys.argv[1] 101 | if os.path.exists(cfg_file): 102 | return cfg_file 103 | else: 104 | print ("!!! ERROR !!! Could not find CONFIG file %s"%cfg_file) 105 | elif len(sys.argv) == 1: 106 | cfg_file = "test.cfg" 107 | print (TOOL_INFO) 108 | print_yellow ("!!! WARNING !!! No Config File Supplied. \nUsing default config file %s"%cfg_file) 109 | print (SAMPLE_CONFIG_FILE) 110 | return cfg_file 111 | 112 | print (TOOL_INFO) 113 | print (SAMPLE_CONFIG_FILE) 114 | sys.exit() 115 | 116 | def get_configs(cfg_file): 117 | config = ConfigParser.RawConfigParser() 118 | config.read(cfg_file) 119 | return config 120 | 121 | def get_password(username): 122 | return getpass("Enter password for %s:"%username) 123 | 124 | def get_credentials(config): 125 | print ("Obtaining ALL User Credentials...") 126 | credentials={} 127 | for s in config.sections(): 128 | if config.has_option(s,"username"): 129 | username=config.get(s,"username") 130 | if username == "": 131 | continue 132 | if credentials.get(username) is None: 133 | credentials.update({username:get_password(username)}) 134 | return credentials 135 | 136 | def process_sections(config,credentials,verify): 137 | 138 | for s in config.sections(): 139 | 140 | # Skip the "General Settings" section 141 | if s == "General Settings": 142 | continue 143 | 144 | # Get Configs 145 | print ("--------------------------------------\nGETTING CONFIGS TO TEST '%s'"%s) 146 | try: 147 | url=config.get(s,"url") 148 | expected_output=config.get(s,"expected_output") 149 | auth_handler=config.get(s,"auth_handler") 150 | except: 151 | print(Back.RED + "ERROR - Failed to acquire configs for %s. Not executing Test"%s) 152 | continue 153 | username=config.get(s,"username") if config.has_option(s,"username") else "" 154 | 155 | # Setup Auth Handler 156 | # print ("Setting Auth Handler...") 157 | auth = None 158 | if auth_handler == "ArcGISServerTokenAuth": 159 | if username == "": 160 | print_red ("ERROR - %s requires credentials. Not executing Test"%auth_handler) 161 | continue 162 | auth=ArcGISServerTokenAuth(username,credentials[username],verify=verify) 163 | elif auth_handler == "ArcGISPortalTokenAuth": 164 | if username == "": 165 | print_red ("ERROR - %s requires credentials. Not executing Test"%auth_handler) 166 | continue 167 | auth=ArcGISPortalTokenAuth(username,credentials[username],verify=verify) 168 | elif auth_handler == "ArcGISServerAuth": 169 | if username == "": 170 | auth=ArcGISServerAuth(verify=verify) 171 | else: 172 | auth=ArcGISServerAuth(username,credentials[username],verify=verify) 173 | elif auth_handler == "ArcGISPortalAuth": 174 | if username == "": 175 | auth=ArcGISPortalAuth(verify=verify) 176 | else: 177 | auth=ArcGISPortalAuth(username,credentials[username],verify=verify) 178 | elif auth_handler == "ArcGISPortalSAMLAuth": 179 | client_id=config.get(s,"client_id") 180 | auth = ArcGISPortalSAMLAuth(client_id) 181 | 182 | #Make Requests 183 | print ("Executing test...") 184 | result=test_auth(auth,url,verify,expected_output) 185 | if result: 186 | print (Back.GREEN + "%s tests passed"%s) 187 | else: 188 | print (Back.RED + "%s tests failed"%s) 189 | 190 | def test_auth(auth,url,verify,expected_output): 191 | 192 | # auth = authenticaiton handler (session().auth = auth) 193 | # url = (str) 194 | # verify = (Bool) Verify the SSL certificates? 195 | # Expected Output = (STR) 196 | 197 | output=True 198 | s = requests.Session() 199 | s.auth=auth 200 | r=s.get(url,verify=verify) 201 | 202 | # Check Status Code 203 | if r.status_code == 200: 204 | print_green("Status Code: ",r.status_code) 205 | else: 206 | print_red("Status Code: ",r.status_code) 207 | output=False 208 | 209 | # Check Expected Output 210 | if r.text == expected_output: 211 | print_green('Expected Output Matches!') 212 | else: 213 | print_red("Expected Output Does Not Match! Output:\n%s"%r.text.encode("UTF-8")) 214 | output=False 215 | 216 | # Check for existance of token 217 | if type(auth) == ArcGISPortalSAMLAuth: 218 | if auth._token_data is not None: 219 | print_green("Access Token is present! %s..."%auth._token_data.get("access_token")[0:10]) 220 | print_green("Refresh Token is present! %s..."%auth._token_data.get("refresh_token")[0:10]) 221 | elif type(auth) == ArcGISPortalTokenAuth or type(auth) == ArcGISServerTokenAuth: 222 | if auth._token.get("token") is not None: 223 | print_green("Token is present! %s..."%auth._token.get("token")[0:10]) 224 | else: 225 | print_red("Token is NOT PRESENT! %s"%str(auth._token)) 226 | output=False 227 | elif auth._instanceof == ArcGISPortalTokenAuth or auth._instanceof == ArcGISServerTokenAuth: 228 | if auth._token.get("token") is not None: 229 | print_green("Token is present! %s..."%auth._token.get("token")[0:10]) 230 | else: 231 | print_red("Token is NOT PRESENT! %s"%str(auth._token)) 232 | output=False 233 | 234 | return output 235 | 236 | 237 | def main(): 238 | 239 | # Get Configs... 240 | cfg_file = get_inputs() 241 | # GET RID OF GLOBAL REFERENCE WHEN NOT DEBUGGING 242 | global config,credentials 243 | config=get_configs(cfg_file) 244 | credentials=get_credentials(config) 245 | verify=config.getboolean("General Settings","verify_certs") 246 | 247 | print_cyan("==== STARTING TESTS ====") 248 | process_sections(config,credentials,verify) 249 | 250 | # Start Tests 251 | """section="ArcGIS Server Token Auth" 252 | url=config.get(section,"url") 253 | username=config.get(section,"username") 254 | expected_output=config.get(section,"expected_output") 255 | auth=ArcGISServerTokenAuth(username,credentials[username],verify=verify) 256 | test_auth(auth,url,verify,expected_output) 257 | 258 | section = "Portal Token Auth" 259 | url=config.get(section,"url") 260 | username=config.get(section,"username") 261 | expected_output=config.get(section,"expected_output") 262 | auth=ArcGISPortalTokenAuth(username,credentials[username],verify=verify) 263 | test_auth(auth,url,verify,expected_output) 264 | """ 265 | 266 | 267 | if __name__ == '__main__': 268 | main() 269 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | requests>=2.13.0 2 | requests-kerberos>=0.11.0 3 | requests-ntlm>=1.0.0 4 | beautifulsoup4>=4.6.0 5 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DOI-BLM/requests-arcgis-auth/e01c7b708638562efebb67b54a1f8a3bbcd1eff0/setup.py --------------------------------------------------------------------------------