BC Ferries Python Library
=========================
This is the Python client library for interacting with information
published on the `BC Ferries mobile
site <http://mobile.bcferries.com/>`__. It is essentially a wrapper
around a BeautifulSoup-powered scraper. Better documentation and tests
are still in the works; feel free to contribute!
This library is used to power project like
`FerryTime <https://ferryti.me>`__. The source code for this library can
be found at `yasyf/bcferries <https://github.com/yasyf/bcferries>`__ on
GitHub.
Installation
------------
``pip install bcferries``
Setup
-----
Some functions require interaction with a geocoding service; the Google
Maps API is used for this. In order to prevent severe rate limiting,
you'll want to acquire an API key. To let ``bcferries`` know about this
key, set it as the ``GOOGLE_MAPS_API_KEY`` environment variable.
Alternatively, you can pass it as an optional keyword argument to the
constructor.
.. code:: python
from bcferries import BCFerries
bc = BCFerries(google_maps_api_key='xxx-xxx-xxx')
Usage
-----
.. code:: python
bc = BCFerries()
Terminals
~~~~~~~~~
.. code:: python
bc.nearest_terminal('Qualicum Beach')
# BCFerriesTerminal(Nanaimo (Duke Pt))
terminals = bc.terminals()
# {u'Horseshoe Bay': BCFerriesTerminal(Horseshoe Bay), u'Tsawwassen': BCFerriesTerminal(Tsawwassen)}
t = terminals['Tsawwassen']
# BCFerriesTerminal(Tsawwassen)
t.updated_at()
# datetime.datetime(2014, 12, 29, 0, 4)
t.next_crossing()
# BCFerriesCrossing(Tsawwassen to Duke Point at 5:15am)
t.location().address
# u'Ferry Causeway, Delta, BC V4M, Canada'
Routes
~~~~~~
.. code:: python
routes = t.routes()
# {u'Tsawwassen to Duke Point': BCFerriesRoute(Tsawwassen to Duke Point)}
r = routes['Tsawwassen to Duke Point']
# BCFerriesRoute(Tsawwassen to Duke Point)
r.from_, r.to
# (BCFerriesTerminal(Tsawwassen), BCFerriesTerminal(Nanaimo (Duke Pt)))
r.distance()
# Distance(61.9591068557)
r.car_waits
# 0
Crossings
~~~~~~~~~
.. code:: python
crossing = r.crossings()['10:45pm']
# BCFerriesCrossing(Tsawwassen to Duke Point at 5:45pm)
crossing.capacity
# BCFerriesCapacity(18% Full)
Schedules
~~~~~~~~~
.. code:: python
schedule = r.scheduled('12:45 PM')
# BCFerriesScheduledCrossing(Queen of Alberni at 12:45 PM)
schedule.status
# u'On Time'
schedule.sailing_time
# datetime.timedelta(0, 7200)
schedule.is_late()
# False
schedule.is_departed()
# True
Fuzzy Results
-------------
All returned dictionaries have fuzzy string matching on they keys.
.. code:: python
routes['Tsawwassen to Duke Point'] == routes['Tsaw to DP']
# True
There is also fuzzy time matching on keys that represent a nearby time.
.. code:: python
r = routes['HBay to DBay']
schedule = r.schedule()
schedule['6:12 PM']
# BCFerriesScheduledCrossing(Queen of Cowichan at 6:30 PM)
``datetime`` objects can also be used as keys.
.. code:: python
from datetime import datetime
datetime.datetime.now()
# datetime.datetime(2014, 12, 28, 10, 42, 35, 630996)
schedule[datetime.datetime.now()]
# BCFerriesScheduledCrossing(Coastal Renaissance at 10:40 AM)
Caching
-------
``bcferries`` caches the 16 most used API calls for up to five minutes
by default. You can change this behavior as below. This must be done
before creating a ``BCFerries`` object.
.. code:: python
import bcferries
import datetime
bcferries.set_cache_size(16)
bcferries.set_cache_timeout(datetime.timedelta(minutes=5))
You can also pass any function the ``ignore_cache`` keyword argument to
bypass the cache, or call the ``flush_cache`` method on ``BCFerries`` to
clear the entire cache.
.. code:: python
terminals = bc.terminals() # initial call takes multiple seconds
terminals = bc.terminals() # repeated call returns almost instantly
terminals = bc.terminals(ignore_cache=True) # takes multiple seconds to return
bc.flush_cache() # wipes the cache
Export
------
You can export any subset of information with a call to ``to_dict`` on
any object. You can also use ``to_fuzzy_dict`` and ``to_json`` as
needed.
By default, complex objects which require further API calls will not be
created, and only their names will be returned. You can disable this
behavior with the ``shallow`` keyword argument. To export all available
information, do this on a ``BCFerries`` instance, and be prepared to
wait a while.
.. code:: python
crossing.capacity
# BCFerriesCapacity(18% Full)
crossing.capacity.to_dict()
# {'passenger_filled': 32, 'mixed_filled': 4, 'name': '18% Full', 'filled': 18}
bc.to_dict() # quick
bc.to_dict(shallow=False) # takes all day