coveralls: 
[![Coverage Status](https://coveralls.io/builds/32196966/badge)](https://coveralls.io/builds/32196966)

Coverage increased (+0.05%) to 89.663% when pulling **6132dcb01b59f3b214c7a03170e47f498785dd5f on getboard** into **181c8b6a62921a7e836ca049d080a23083310407 on master**.

diff --git a/.travis.yml b/.travis.yml
index 19aa694..5d4debb 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -11,7 +11,7 @@ python:
 install:
   # pinning coverage package until bugs with coveralls plugin is fixed
   # https://github.com/z4r/python-coveralls/issues/73
-  - pip install tox wheel python-coveralls "coverage<5.0"
+  - pip install tox tox-factor wheel python-coveralls "coverage<5.0"
 
 script:
   - echo $TRAVIS_PYTHON_VERSION
@@ -20,8 +20,7 @@ script:
   # For CPython the TravisCI env var mapping should be: 3.8 -> py38
   - '[ "$TRAVIS_PYTHON_VERSION" = "pypy3.5" ] && export PYVER=`echo $TRAVIS_PYTHON_VERSION | tr "." "\n" | head -n 1` || export PYVER=py`echo $TRAVIS_PYTHON_VERSION | sed "s/\.//" | sed "s/^py//"`'
   - echo $PYVER
-  - tox -e $PYVER-lint
-  - tox -e $PYVER-test
+  - tox -f $PYVER
   # Only publish coverage metrics for the latest supported Python version
   - '[ "$TRAVIS_PYTHON_VERSION" = "3.8" ] && coveralls || echo Skipping Coveralls'
 
diff --git a/docs/conf.py b/docs/conf.py
index 4a1aeb1..6b82dda 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -1,21 +1,15 @@
-# -*- coding: utf-8 -*-
-#
-# Configuration file for the Sphinx documentation builder.
-#
-# This file does only contain a selection of the most common options. For a
-# full list see the documentation:
-# http://www.sphinx-doc.org/en/stable/config
+"""
+Configuration file for the Sphinx documentation builder.
 
-# -- Path setup --------------------------------------------------------------
+This file does only contain a selection of the most common options. For a
+full list see the documentation:
+http://www.sphinx-doc.org/en/stable/config
+"""
 
-# If extensions (or modules to document with autodoc) are in another directory,
-# add these directories to sys.path here. If the directory is relative to the
-# documentation root, use os.path.abspath to make it absolute, like shown here.
-#
 import ast
 import os
 import sys
-import sphinx_rtd_theme
+from sphinx.ext.intersphinx import InventoryAdapter
 
 # If extensions (or modules to document with autodoc) are in another directory,
 # add these directories to sys.path here. If the directory is relative to the
@@ -27,7 +21,7 @@ sys.path.insert(0, _src_dir)
 
 # -- Project information -----------------------------------------------------
 
-copyright = '2020, Kevin S. Phillips'
+copyright = '2020, Kevin S. Phillips'  # pylint: disable=redefined-builtin
 author = 'Kevin S. Phillips'
 _proj_props = ast.literal_eval(open('../project.prop').read())
 _proj_dir = os.path.join(_src_dir, _proj_props["NAME"])
@@ -45,23 +39,7 @@ version = _proj_props["VERSION"]
 # The full version, including alpha/beta/rc tags.
 release = version
 
-# Configure automatic API documentation
-apidoc_module_dir = _proj_dir
-apidoc_output_dir = os.path.join(_base_path, "api")
-apidoc_separate_modules = True
-napoleon_numpy_docstring = False
-autoclass_content = "both"
-napoleon_include_special_with_doc = False
-
 # -- General configuration ---------------------------------------------------
-
-# If your documentation needs a minimal Sphinx version, state it here.
-#
-# needs_sphinx = '1.0'
-
-# Add any Sphinx extension module names here, as strings. They can be
-# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
-# ones.
 extensions = [
     'sphinx.ext.autodoc',
     'sphinx.ext.intersphinx',
@@ -72,125 +50,82 @@ extensions = [
     'sphinx_rtd_theme',
 ]
 
-# Add any paths that contain templates here, relative to this directory.
 templates_path = ['_templates']
-
-# The suffix(es) of source filenames.
-# You can specify multiple suffix as a list of string:
-#
-# source_suffix = ['.rst', '.md']
 source_suffix = '.rst'
-
-# The master toctree document.
 master_doc = 'index'
-
-# The language for content autogenerated by Sphinx. Refer to documentation
-# for a list of supported languages.
-#
-# This is also used if you do content translation via gettext catalogs.
-# Usually you set "language" from the command line for these cases.
-language = None
-
-# List of patterns, relative to source directory, that match files and
-# directories to ignore when looking for source files.
-# This pattern also affects html_static_path and html_extra_path .
 exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
-
-# The name of the Pygments (syntax highlighting) style to use.
 pygments_style = 'sphinx'
 
+# -- Options for apidoc/napoleon extensions ------------------------------------
+apidoc_module_dir = _proj_dir
+apidoc_output_dir = os.path.join(_base_path, "api")
+apidoc_separate_modules = True
+napoleon_numpy_docstring = False
+autoclass_content = "both"
+napoleon_include_special_with_doc = False
 
 # -- Options for HTML output -------------------------------------------------
-
-# The theme to use for HTML and HTML Help pages.  See the documentation for
-# a list of builtin themes.
-#
 html_theme = 'sphinx_rtd_theme'
-
-# Theme options are theme-specific and customize the look and feel of a theme
-# further.  For a list of options available for each theme, see the
-# documentation.
-#
 html_theme_options = {
     "style_external_links": True,
 }
 
-# Add any paths that contain custom static files (such as style sheets) here,
-# relative to this directory. They are copied after the builtin static files,
-# so a file named "default.css" will overwrite the builtin "default.css".
-html_static_path = []
-
-# Custom sidebar templates, must be a dictionary that maps document names
-# to template names.
-#
-# The default sidebars (for documents that don't match any pattern) are
-# defined by theme itself.  Builtin themes are using these templates by
-# default: ``['localtoc.html', 'relations.html', 'sourcelink.html',
-# 'searchbox.html']``.
-#
-# html_sidebars = {}
-
-
-# -- Options for HTMLHelp output ---------------------------------------------
-
-# Output file base name for HTML help builder.
-htmlhelp_basename = 'friendlypinsdoc'
-
-
-# -- Options for LaTeX output ------------------------------------------------
-
-latex_elements = {
-    # The paper size ('letterpaper' or 'a4paper').
-    #
-    # 'papersize': 'letterpaper',
-
-    # The font size ('10pt', '11pt' or '12pt').
-    #
-    # 'pointsize': '10pt',
-
-    # Additional stuff for the LaTeX preamble.
-    #
-    # 'preamble': '',
-
-    # Latex figure (float) alignment
-    #
-    # 'figure_align': 'htbp',
+# -- Options for intersphinx extension ---------------------------------------
+intersphinx_mapping = {
+    "python": ("https://docs.python.org/", None),
+    "requests": ("https://requests.readthedocs.io/en/master/", None),
 }
 
-# Grouping the document tree into LaTeX files. List of tuples
-# (source start file, target name, title,
-#  author, documentclass [howto, manual, or own class]).
-latex_documents = [
-    (master_doc, 'friendlypins.tex', 'friendlypins Documentation',
-     'Kevin S. Phillips', 'manual'),
-]
-
-
-# -- Options for manual page output ------------------------------------------
-
-# One entry per manual page. List of tuples
-# (source start file, name, description, authors, manual section).
-man_pages = [
-    (master_doc, 'friendlypins', 'friendlypins Documentation',
-     [author], 1)
-]
-
-
-# -- Options for Texinfo output ----------------------------------------------
-
-# Grouping the document tree into Texinfo files. List of tuples
-# (source start file, target name, title, author,
-#  dir menu entry, description, category)
-texinfo_documents = [
-    (master_doc, 'friendlypins', 'friendlypins Documentation',
-     author, 'friendlypins', 'One line description of project.',
-     'Miscellaneous'),
-]
-
-
-# -- Extension configuration -------------------------------------------------
+intersphinx_aliases = {
+    'py:exception': {
+        'requests.HTTPError': 'requests.exceptions.HTTPError'
+    }
+}
 
-# -- Options for intersphinx extension ---------------------------------------
 
-# Example configuration for intersphinx: refer to the Python standard library.
-intersphinx_mapping = {'https://docs.python.org/': None}
\ No newline at end of file
+def add_intersphinx_aliases_to_inv(app):
+    """Workaround for data type mismatches between intersphinx document sources
+
+    Implementation based on a workaround found here:
+    https://github.com/sphinx-doc/sphinx/issues/5603
+
+    The calling code need only define a dictionary that maps the source object
+    as it appears in the Sphinx object tree, to the actual location for the
+    object definition in an object.inv inventory file. The syntax looks like
+    this:
+
+    intersphinx_aliases = {
+        'dt-domain': {
+            'src-obj-name': 'target-obj-name'
+        }
+    }
+
+    TIP: when debugging intersphinx mapping problems, it is helpful to use
+    the sphobjinv tool:
+        https://pypi.org/project/sphobjinv/
+
+    Example use:
+    sphobjinv suggest https://requests.readthedocs.io/en/master/ HTTPError -su
+    """
+    inventories = InventoryAdapter(app.builder.env)
+
+    for domain, mapping in app.config.intersphinx_aliases.items():
+        if domain not in inventories.main_inventory:
+            raise NotImplementedError(
+                "Domain {0} not found in Sphinx inventory".format(domain)
+            )
+        for source, target in mapping.items():
+            if source not in inventories.main_inventory[domain]:
+                raise NotImplementedError(
+                    "Source object {0} not found in Sphinx domain {1}".format(
+                        source, domain
+                    )
+                )
+            inventories.main_inventory[domain][target] = \
+                inventories.main_inventory[domain][source]
+
+
+def setup(app):
+    """Custom Sphinx extention manager entry point method"""
+    app.add_config_value('intersphinx_aliases', {}, 'env')
+    app.connect('builder-inited', add_intersphinx_aliases_to_inv)
diff --git a/src/friendlypins/api.py b/src/friendlypins/api.py
index 81bc8b0..120116c 100644
--- a/src/friendlypins/api.py
+++ b/src/friendlypins/api.py
@@ -1,6 +1,7 @@
 """Primary entry point for the Friendly Pinterest library"""
 import logging
 from friendlypins.user import User
+from friendlypins.board import Board
 from friendlypins.utils.rest_io import RestIO
 
 
@@ -17,6 +18,23 @@ class API(object):  # pylint: disable=too-few-public-methods
         self._log = logging.getLogger(__name__)
         self._io = RestIO(personal_access_token)
 
+    def get_board_by_id(self, board_id):
+        """Locates a specific Pinterest board given it's internal identifier
+
+        NOTE: this API assumes that the ID provided references a valid board.
+        If it does not, the object returned will be invalid and any attempts
+        to access data from the board will result in an error.
+
+        Args:
+            board_id (int):
+                the unique identifier for the board
+
+        Returns:
+            Board: reference to the Pinterest board
+        """
+        board_url = "boards/{0}".format(board_id)
+        return Board(board_url, self._io)
+
     @property
     def user(self):
         """User: Gets all primitives associated with the authenticated user"""
diff --git a/src/friendlypins/board.py b/src/friendlypins/board.py
index 7eb42de..04966e8 100644
--- a/src/friendlypins/board.py
+++ b/src/friendlypins/board.py
@@ -7,18 +7,86 @@ from friendlypins.pin import Pin
 class Board(object):
     """Abstraction around a Pinterest board"""
 
-    def __init__(self, data, rest_io):
+    def __init__(self, url, rest_io, json_data=None):
         """
         Args:
-            data (dict): Raw Pinterest API data describing the board
+            url (str): URL for this board, relative to the API root
             rest_io (RestIO): reference to the Pinterest REST API
+            json_data (dict):
+                Optional JSON response data describing this board
+                if not provided, the class will lazy load response data
+                when needed
         """
         self._log = logging.getLogger(__name__)
-        self._data = data
+        self._data_cache = json_data
+        self._relative_url = url
         self._io = rest_io
 
+    def refresh(self):
+        """Updates cached response data describing the state of this board
+
+        NOTE: This method simply clears the internal cache, and updated
+        information will automatically be pulled on demand as additional
+        queries are made through the API"""
+        self._data_cache = None
+
+    @staticmethod
+    def default_fields():
+        """list (str): list of fields we pre-populate when loading board data"""
+        return [
+            "id",
+            "name",
+            "url",
+            "description",
+            "creator",
+            "created_at",
+            "counts",
+            "image",
+            "reason",
+            "privacy"
+        ]
+
+    @property
+    def _data(self):
+        """dict: gets response data, either from the internal cache or from the
+        REST API"""
+        if self._data_cache is not None:
+            return self._data_cache
+        self._log.debug("Lazy loading board data for: %s", self._relative_url)
+        properties = {
+            "fields": ','.join(self.default_fields())
+        }
+        temp = self._io.get(self._relative_url, properties)
+        assert "data" in temp
+        self._data_cache = temp["data"]
+
+        return self._data_cache
+
+    @classmethod
+    def from_json(cls, json_data, rest_io):
+        """Factory method that instantiates an instance of this class
+        from JSON response data loaded by the caller
+
+        Args:
+            json_data (dict):
+                pre-loaded response data describing the board
+            rest_io (RestIO):
+                pre-initialized session object for communicating with the
+                REST API
+
+        Returns:
+            Board: instance of this class encapsulating the response data
+        """
+        board_url = "boards/{0}".format(json_data["id"])
+        return Board(board_url, rest_io, json_data)
+
+    @property
+    def json(self):
+        """dict: returns raw json representation of this object"""
+        return self._data
+
     def __str__(self):
-        return json.dumps(dict(self._data), sort_keys=True, indent=4)
+        return json.dumps(self._data, sort_keys=True, indent=4)
 
     def __repr__(self):
         return "<{0} ({1})>".format(self.__class__.__name__, self.name)
@@ -51,7 +119,7 @@ class Board(object):
     @property
     def pins(self):
         """Pin: Generator for iterating over the pins linked to this board"""
-        self._log.debug('Loading pins for board %s...', self.name)
+        self._log.debug('Loading pins for board %s...', self._relative_url)
 
         properties = {
             "fields": ','.join([
@@ -72,7 +140,7 @@ class Board(object):
             ])
         }
 
-        path = "boards/{0}/pins".format(self.unique_id)
+        path = "{0}/pins".format(self._relative_url)
         for cur_page in self._io.get_pages(path, properties):
             assert 'data' in cur_page
 
@@ -81,8 +149,8 @@ class Board(object):
 
     def delete(self):
         """Removes this board and all pins attached to it"""
-        self._log.debug('Deleting board %s', repr(self))
-        self._io.delete('boards/{0}'.format(self.unique_id))
+        self._log.debug('Deleting board %s', self._relative_url)
+        self._io.delete(self._relative_url)
 
 
 if __name__ == "__main__":  # pragma: no cover
diff --git a/src/friendlypins/exceptions.py b/src/friendlypins/exceptions.py
index 3a4be89..e0278c6 100644
--- a/src/friendlypins/exceptions.py
+++ b/src/friendlypins/exceptions.py
@@ -2,7 +2,7 @@
 from datetime import datetime
 from dateutil import tz
 from humanize import naturaltime
-from requests import HTTPError
+from requests.exceptions import HTTPError
 from friendlypins.headers import Headers
 
 
@@ -19,7 +19,7 @@ class RateLimitException(HTTPError):
 
     @property
     def rate_renewal(self):
-        """datetime.datemtime: time, in the current locale, when requests will
+        """datetime.datetime: time, in the current locale, when requests will
         be allowed once again"""
         return self.pin_headers.time_to_refresh
 
diff --git a/src/friendlypins/user.py b/src/friendlypins/user.py
index 0d8670d..a74c40d 100644
--- a/src/friendlypins/user.py
+++ b/src/friendlypins/user.py
@@ -18,6 +18,22 @@ class User(object):
         self._relative_url = url
         self._data_cache = None
 
+    @staticmethod
+    def default_fields():
+        """list (str): list of fields we pre-populate when loading user data"""
+        return [
+            "id",
+            "username",
+            "first_name",
+            "last_name",
+            "bio",
+            "created_at",
+            "counts",
+            "image",
+            "account_type",
+            "url"
+        ]
+
     def refresh(self):
         """Updates cached response data describing the state of this user
 
@@ -35,25 +51,14 @@ class User(object):
         limitations.
         """
         if self._data_cache is not None:
-            return self._data_cache["data"]
+            return self._data_cache
         self._log.debug("Getting authenticated user details...")
 
-        fields = ",".join([
-            "id",
-            "username",
-            "first_name",
-            "last_name",
-            "bio",
-            "created_at",
-            "counts",
-            "image",
-            "account_type",
-            "url"
-        ])
-        self._data_cache = self._io.get(self._relative_url, {"fields": fields})
-        assert 'data' in self._data_cache
-        return self._data_cache["data"]
-
+        fields = ",".join(self.default_fields())
+        temp = self._io.get(self._relative_url, {"fields": fields})
+        assert 'data' in temp
+        self._data_cache = temp["data"]
+        return self._data_cache
 
     def __str__(self):
         return json.dumps(dict(self._data), sort_keys=True, indent=4)
@@ -108,18 +113,7 @@ class User(object):
         self._log.debug('Loading boards for user %s...', self._relative_url)
 
         properties = {
-            "fields": ','.join([
-                "id",
-                "name",
-                "url",
-                "description",
-                "creator",
-                "created_at",
-                "counts",
-                "image",
-                "reason",
-                "privacy"
-            ])
+            "fields": ','.join(Board.default_fields())
         }
 
         board_url = "{0}/boards".format(self._relative_url)
@@ -127,7 +121,7 @@ class User(object):
             assert 'data' in cur_page
 
             for cur_item in cur_page['data']:
-                yield Board(cur_item, self._io)
+                yield Board.from_json(cur_item, self._io)
 
     def create_board(self, name, description=None):
         """Creates a new board for the currently authenticated user
@@ -140,18 +134,7 @@ class User(object):
             Board: reference to the newly created board
         """
         properties = {
-            "fields": ','.join([
-                "id",
-                "name",
-                "url",
-                "description",
-                "creator",
-                "created_at",
-                "counts",
-                "image",
-                "reason",
-                "privacy"
-            ])
+            "fields": ','.join(Board.default_fields())
         }
 
         data = {"name": name}
@@ -159,7 +142,7 @@ class User(object):
             data["description"] = description
 
         result = self._io.post("boards", data, properties)
-        return Board(result['data'], self._io)
+        return Board.from_json(result['data'], self._io)
 
 
 if __name__ == "__main__":  # pragma: no cover
diff --git a/tox.ini b/tox.ini
index 7ae8817..b764b48 100644
--- a/tox.ini
+++ b/tox.ini
@@ -30,6 +30,8 @@ deps =
 # version - v3.8 in this case
 commands =
     py38-lint: python -m pylint setup.py
+    py38-lint: python -m pylint -d invalid-name docs/conf.py
     py38-lint: python -m pylint ./src/{env:PROJECT_PATH}
     test: python -m pytest {posargs} ./tests -v --cov-report html --cov {env:PROJECT_PATH} --no-cov-on-fail
-    py38-docs: python -m sphinx -b html -a -n -W --keep-going ./docs ./htmldocs
+    py38-docs: python -c "import shutil; shutil.rmtree('htmldocs', ignore_errors=True)"
+    py38-docs: python -m sphinx -b html -anW --keep-going ./docs ./htmldocs

add a find board by id method to api
In another effort to minimize the hits to the pinterest api we should add a helper method that returns a Board object given an ID number. Further, we should optimize this getter so that it lazy-loads the response data describing the board only when necessary.
diff --git a/tests/test_board.py b/tests/test_board.py
index 94753aa..df1aaf1 100644
--- a/tests/test_board.py
+++ b/tests/test_board.py
@@ -17,19 +17,42 @@ def test_board_properties():
     }
 
     mock_io = mock.MagicMock()
-    obj = Board(sample_data, mock_io)
+    obj = Board("boards/"+str(expected_id), mock_io, sample_data)
     assert obj.unique_id == expected_id
     assert obj.name == expected_name
     assert obj.url == expected_url
     assert obj.num_pins == expected_pin_count
 
 
-def test_get_pins():
+def test_cache_refresh():
+    expected_url = 'https://www.pinterest.com/MyUserName/'
     data = {
-        'id': '987654321',
-        'name': 'MyBoard'
+        'url': expected_url,
     }
 
+    mock_io = mock.MagicMock()
+    mock_io.get.return_value = {"data": data}
+    obj = Board("boards/1234", mock_io)
+    # If we make multiple requests for API data, we should only get
+    # a single hit to the remote API endpoint
+    assert expected_url == obj.url
+    assert expected_url == obj.url
+    mock_io.get.assert_called_once()
+
+    # Calling refresh should clear our internal response cache
+    # which should not require any additional API calls
+    obj.refresh()
+    mock_io.get.assert_called_once()
+
+    # Subsequent requests for additional data should reload the cache,
+    # and then preserve / reuse the cache data for all subsequent calls,
+    # limiting the number of remote requests
+    assert expected_url == obj.url
+    assert expected_url == obj.url
+    assert mock_io.get.call_count == 2
+
+
+def test_get_pins():
     expected_id = 1234
     expected_url = "https://www.pinterest.ca/MyName/MyPin/"
     expected_note = "My Pin descriptive text"
@@ -52,7 +75,7 @@ def test_get_pins():
 
     mock_io = mock.MagicMock()
     mock_io.get_pages.return_value = [expected_data]
-    obj = Board(data, mock_io)
+    obj = Board("boards/1234", mock_io)
 
     result = list()
     for item in obj.pins:
@@ -66,13 +89,9 @@ def test_get_pins():
 
 
 def test_delete():
-    data = {
-        "id": "12345678",
-        "name": "MyBoard"
-    }
-
     mock_io = mock.MagicMock()
-    obj = Board(data, mock_io)
+    expected_url = "boards/1234"
+    obj = Board(expected_url, mock_io)
     obj.delete()
 
-    mock_io.delete.assert_called_once()
+    mock_io.delete.assert_called_once_with(expected_url)
diff --git a/tests/test_user.py b/tests/test_user.py
index ffacb62..b25d47a 100644
--- a/tests/test_user.py
+++ b/tests/test_user.py
@@ -61,11 +61,6 @@ def test_cache_refresh():
 
 
 def test_get_boards():
-    data = {
-        "first_name": "John",
-        "last_name": "Doe"
-    }
-
     expected_id = 1234
     expected_name = "MyBoard"
     expected_url = "https://www.pinterest.ca/MyName/MyBoard/"
@@ -82,7 +77,7 @@ def test_get_boards():
 
     mock_io = mock.MagicMock()
     mock_io.get_pages.return_value = [expected_data]
-    obj = User(data, mock_io)
+    obj = User("me", mock_io)
 
     result = list()
     for item in obj.boards:
@@ -97,11 +92,6 @@ def test_get_boards():
 def test_create_board():
     expected_name = "My Board"
     expected_desc = "My new board is about this stuff..."
-    data = {
-        "id": "1234",
-        "first_name": "Jonh",
-        "last_name": "Doe"
-    }
     mock_io = mock.MagicMock()
     mock_io.post.return_value = {
         "data": {
@@ -110,7 +100,7 @@ def test_create_board():
             "id": "12345"
         }
     }
-    obj = User(data, mock_io)
+    obj = User("me", mock_io)
 
     board = obj.create_board(expected_name, expected_desc)
     mock_io.post.assert_called_once()

pip install -e .[dev]
parse_log_pytest
requirements.txt
pytest pytest-cov mock pylint sphinx tox radon
apt-get update apt-get install -y gcc
3.9
requirements/base.txt
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
alabaster==0.7.16
astroid==3.3.9
babel==2.17.0
cachetools==5.5.2
certifi==2025.1.31
chardet==5.2.0
charset-normalizer==3.4.1
colorama==0.4.6
coverage==4.5.4
dateutils==0.6.12
dill==0.3.9
distlib==0.3.9
docutils==0.21.2
exceptiongroup==1.2.2
filelock==3.18.0
-e git+https://github.com/TheFriendlyCoder/friendlypins.git@181c8b6a62921a7e836ca049d080a23083310407#egg=friendlypins
humanize==4.12.2
idna==3.10
imagesize==1.4.1
importlib_metadata==8.6.1
iniconfig==2.1.0
isort==6.0.1
Jinja2==3.1.6
mando==0.7.1
MarkupSafe==3.0.2
mccabe==0.7.0
mock==5.2.0
packaging==24.2
pbr==6.1.1
pillow==11.1.0
platformdirs==4.3.7
pluggy==1.5.0
Pygments==2.19.1
pylint==3.3.6
pyproject-api==1.9.0
pytest==8.3.5
pytest-cov==2.10.1
python-dateutil==2.9.0.post0
pytz==2025.2
radon==6.0.1
requests==2.32.3
six==1.17.0
snowballstemmer==2.2.0
Sphinx==7.4.7
sphinx-rtd-theme==3.0.2
sphinxcontrib-apidoc==0.5.0
sphinxcontrib-applehelp==2.0.0
sphinxcontrib-devhelp==2.0.0
sphinxcontrib-htmlhelp==2.1.0
sphinxcontrib-jquery==4.1
sphinxcontrib-jsmath==1.0.1
sphinxcontrib-qthelp==2.0.0
sphinxcontrib-serializinghtml==2.0.0
tomli==2.2.1
tomlkit==0.13.2
tox==4.25.0
tox-factor==0.1.2
tox-pyenv==1.1.0
tqdm==4.67.1
typing_extensions==4.13.0
urllib3==2.3.0
virtualenv==20.29.3
zipp==3.21.0

name: friendlypins
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.4.4=h6a678d5_1
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=3.0.16=h5eee18b_0
  - pip=25.0=py39h06a4308_0
  - python=3.9.21=he870216_1
  - readline=8.2=h5eee18b_0
  - setuptools=75.8.0=py39h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - tzdata=2025a=h04d1e81_0
  - wheel=0.45.1=py39h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - alabaster==0.7.16
      - astroid==3.3.9
      - babel==2.17.0
      - cachetools==5.5.2
      - certifi==2025.1.31
      - chardet==5.2.0
      - charset-normalizer==3.4.1
      - colorama==0.4.6
      - coverage==4.5.4
      - dateutils==0.6.12
      - dill==0.3.9
      - distlib==0.3.9
      - docutils==0.21.2
      - exceptiongroup==1.2.2
      - filelock==3.18.0
      - humanize==4.12.2
      - idna==3.10
      - imagesize==1.4.1
      - importlib-metadata==8.6.1
      - iniconfig==2.1.0
      - isort==6.0.1
      - jinja2==3.1.6
      - mando==0.7.1
      - markupsafe==3.0.2
      - mccabe==0.7.0
      - mock==5.2.0
      - packaging==24.2
      - pbr==6.1.1
      - pillow==11.1.0
      - platformdirs==4.3.7
      - pluggy==1.5.0
      - pygments==2.19.1
      - pylint==3.3.6
      - pyproject-api==1.9.0
      - pytest==8.3.5
      - pytest-cov==2.10.1
      - python-dateutil==2.9.0.post0
      - pytz==2025.2
      - radon==6.0.1
      - requests==2.32.3
      - six==1.17.0
      - snowballstemmer==2.2.0
      - sphinx==7.4.7
      - sphinx-rtd-theme==3.0.2
      - sphinxcontrib-apidoc==0.5.0
      - sphinxcontrib-applehelp==2.0.0
      - sphinxcontrib-devhelp==2.0.0
      - sphinxcontrib-htmlhelp==2.1.0
      - sphinxcontrib-jquery==4.1
      - sphinxcontrib-jsmath==1.0.1
      - sphinxcontrib-qthelp==2.0.0
      - sphinxcontrib-serializinghtml==2.0.0
      - tomli==2.2.1
      - tomlkit==0.13.2
      - tox==4.25.0
      - tox-factor==0.1.2
      - tox-pyenv==1.1.0
      - tqdm==4.67.1
      - typing-extensions==4.13.0
      - urllib3==2.3.0
      - virtualenv==20.29.3
      - zipp==3.21.0
prefix: /opt/conda/envs/friendlypins

tests/test_board.py::test_board_properties tests/test_board.py::test_cache_refresh tests/test_board.py::test_get_pins tests/test_board.py::test_delete
tests/test_user.py::test_user_properties tests/test_user.py::test_cache_refresh tests/test_user.py::test_get_boards tests/test_user.py::test_create_board
docs/conf.py src/friendlypins/board.py .travis.yml src/friendlypins/user.py src/friendlypins/exceptions.py tox.ini src/friendlypins/api.py
docs/conf.py src/friendlypins/board.py .travis.yml src/friendlypins/user.py src/friendlypins/exceptions.py tox.ini src/friendlypins/api.py