Skip to content

Commit

Permalink
Misc updates (#32)
Browse files Browse the repository at this point in the history
* fix readme, actions

* update readme link

* push only

* fix cache

* pin requires better

* update requires, black

* expose readme as data

* tox for py3.6

* drop 36

* pin pip

* bump version
  • Loading branch information
nolanbconaway authored Nov 21, 2023
1 parent 6bef524 commit ff9e857
Show file tree
Hide file tree
Showing 12 changed files with 84 additions and 124 deletions.
16 changes: 6 additions & 10 deletions .github/workflows/push.yml
Original file line number Diff line number Diff line change
@@ -1,17 +1,14 @@
name: Push

on: [push, pull_request]
on: push

jobs:
build:
runs-on: ${{matrix.os}}
strategy:
matrix:
os: [ubuntu-latest]
python-version: ["3.7", "3.8", "3.9", "3.10"]
include:
- python-version: "3.6"
os: "ubuntu-20.04"
python-version: ["3.7", "3.8", "3.9", "3.10", "3.11", "3.12"]

steps:
- uses: actions/checkout@v3
Expand All @@ -25,14 +22,13 @@ jobs:
uses: actions/cache@v3
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/setup.py') }}
restore-keys: |
${{ runner.os }}-pip-
key: |
${{ format('pip-{0}-{1}', matrix.python-version, hashFiles('setup.py')) }}
- name: Install Dependencies
run: |
python -m pip install --upgrade pip
pip install --editable .[dev]
pip install pip==23.*
pip install .[dev]
- name: Black
run: black src test --check --verbose
Expand Down
12 changes: 5 additions & 7 deletions .github/workflows/release_to_pypi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,23 +12,21 @@ jobs:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
with:
python-version: "3.7"
python-version: "3.10"

- name: Set up Cache
uses: actions/cache@v3
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/setup.py') }}
restore-keys: |
${{ runner.os }}-pip-
key: pip-3.9-${{ hashFiles('setup.py') }}

- name: Install Dependencies
run: |
pip install --upgrade pip
pip install twine wheel --upgrade
pip install pip==23.*
pip install twine==4.* build==1.*
- name: Build Distribution
run: python setup.py sdist bdist_wheel
run: python -m build

- name: Publish Python distribution to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
Expand Down
49 changes: 6 additions & 43 deletions readme.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Python MTA Utilities

[![badge](https://github.com/nolanbconaway/underground/workflows/Push/badge.svg)](https://github.com/nolanbconaway/underground/actions)
[![codecov](https://codecov.io/gh/nolanbconaway/underground/branch/master/graph/badge.svg)](https://codecov.io/gh/nolanbconaway/underground)
[![codecov](https://codecov.io/gh/nolanbconaway/underground/branch/main/graph/badge.svg)](https://codecov.io/gh/nolanbconaway/underground)
[![PyPI - Python Version](https://img.shields.io/pypi/pyversions/underground)](https://pypi.org/project/underground/)
[![PyPI](https://img.shields.io/pypi/v/underground)](https://pypi.org/project/underground/)

Expand All @@ -24,32 +24,6 @@ pip install git+https://github.com/nolanbconaway/underground.git#egg=underground
To request data from the MTA, you'll also need a free API key.
[Register here](https://api.mta.info/).

### Version 0.2.7.4 vs 0.3.0

On May 1 2020, the MTA is sunsetting the [datamine.mta.info](http://datamine.mta.info/) service. The new API ([api.mta.info](https://api.mta.info/)) provides identical data but with a new request API.

Users of 0.2.x will need to migrate by doing the following:

1. **Get a new API key at [api.mta.info](https://api.mta.info/).** This key is longer than the one provided by the datamine API. Underground understands this key in the same way as the old one.
2. **Replace all feed IDs with route IDs or URLs.** The feed IDs have changed for the new API, and not all feeds have IDs any more. Version 0.3 of Underground was built with a `route_or_url` concept for feed selection. Users may provide the URL for the feed they want (see [this page](https://api.mta.info/#/subwayRealTimeFeeds)), or they may provide a route ID (in which case the appropriate URL is then selected).

Code from v0.2.x such as this:

```python
feed = SubwayFeed.get(metadata.get_feed_id('Q'))
```

Now becomes in v0.3:

```python
# under the hood, the correct URL is selected.
feed = SubwayFeed.get('Q')

# or
url = 'https://api-endpoint.mta.info/Dataservice/mtagtfsfeeds/nyct%2Fgtfs-nqrw'
feed = SubwayFeed.get(url)
```

## Python API

Once you have your API key, use the Python API like:
Expand Down Expand Up @@ -102,22 +76,6 @@ feed = SubwayFeed.get(URL)

The `underground` command line tool is also installed with the package.

```
$ underground --help
Usage: underground [OPTIONS] COMMAND [ARGS]...
Command line handlers for MTA realtime data.
Options:
--help Show this message and exit.
Commands:
feed Request an MTA feed.
findstops Find your stop ID.
stops Print out train departure times for all stops on a subway line.
version Print the underground version.
```

### `feed`
```
$ underground feed --help
Expand Down Expand Up @@ -167,6 +125,11 @@ Options:
provided.
-t, --timezone TEXT Output timezone. Ignored if --epoch. Default to NYC
time.
-s, --stalled-timeout INTEGER Number of seconds between the last movement
of a train and the API update before
considering a train stalled. Default is 90 as
recommended by the MTA. Numbers less than 1
disable this check.
--help Show this message and exit.
```

Expand Down
22 changes: 12 additions & 10 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,23 @@
VERSION = (THIS_DIRECTORY / "src" / "underground" / "version").read_text().strip()

INSTALL_REQUIRES = [
"requests>=2.22",
"requests==2.*",
"google~=2.0",
"gtfs-realtime-bindings==0.0.6",
"protobuf>=3.19.6,<=3.20.3",
"protobuf3-to-dict>=0.1.5",
"click~=7.0",
"protobuf3-to-dict==0.1.*",
"click>=7,<9",
"pydantic~=1.9.2",
"pytz>=2019.2",
]

DEV_REQUIRES = [
"pytest>=5.0",
"tox>=3.13",
"black==19.10b0",
"pytest-cov>=2.8",
"codecov>=2.0",
"requests-mock>=1.7.0",
"pytest==7.*",
"tox==4.*",
"black==23.*",
"pytest-cov==4.*",
"codecov==2.*",
"requests-mock==1.*",
]

# use readme as long description
Expand All @@ -40,11 +40,12 @@
author_email="nolanbconaway@gmail.com",
url="https://github.com/nolanbconaway/underground",
classifiers=[
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
],
keywords=["nyc", "transit", "subway", "command-line", "cli"],
license="MIT",
Expand All @@ -54,4 +55,5 @@
extras_require=dict(dev=DEV_REQUIRES),
entry_points={"console_scripts": ["underground = underground.cli.cli:entry_point"]},
package_data={"underground": ["version"]},
data_files=[("", ["readme.md"])], # add the readme
)
2 changes: 1 addition & 1 deletion src/underground/cli/feed.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ def main(route_or_url, api_key, output_json, retries):
\b
underground feed Q --json > feed_nrqw.json
\b
URL='https://api-endpoint.mta.info/Dataservice/mtagtfsfeeds/nyct%2Fgtfs-nqrw' &&
underground feed $URL --json > feed_nrqw.json
Expand Down
4 changes: 2 additions & 2 deletions src/underground/cli/findstops.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@ def request_data() -> zipfile.ZipFile:
)
def main(query, output_json):
"""Find your stop ID.
Query a location and look for your stop ID, like:
$ underground findstops parkside av
"""
query_str = " ".join(query).lower().strip() # make into single string
Expand Down
25 changes: 12 additions & 13 deletions src/underground/feed.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@ class EmptyFeedError(Exception):

def load_protobuf(protobuf_bytes: bytes) -> dict:
"""Process a protobuf bytes object into native python.
Parameters
----------
protobuf_bytes : bytes
Protobuuf data, as returned from the raw request.
Returns
-------
Processed feed data.
Expand All @@ -42,15 +42,15 @@ def request(route_or_url: str, api_key: str = None) -> bytes:
"""Send a HTTP GET request to the MTA for realtime feed data.
Occassionally a feed is requested as the MTA is writing updated data to the file,
and the feed's contents are not complete. This function does _not_ validate the
and the feed's contents are not complete. This function does _not_ validate the
contents of the data, but only returns the request contents as served by the MTA.
Parameters
----------
route_or_url : str
Route ID or feed url (per ``https://api.mta.info/#/subwayRealTimeFeeds``).
api_key : str
MTA API key. If not provided, it will be read from the $MTA_API_KEY env
MTA API key. If not provided, it will be read from the $MTA_API_KEY env
variable.
Returns
Expand Down Expand Up @@ -86,28 +86,28 @@ def request_robust(
"""Request feed data with validations and retries.
Occassionally a feed is requested as the MTA is writing updated data to the file,
and the feed's contents are not complete. This function validates data completeness
and retries if the data are not complete. Since we are processing the protobuf
and the feed's contents are not complete. This function validates data completeness
and retries if the data are not complete. Since we are processing the protobuf
anyway, there is an option to return the processed data as familiar python objects.
Parameters
----------
route_or_url : str
Route ID or feed url (per ``https://api.mta.info/#/subwayRealTimeFeeds``).
retries : int
Number of retry attempts, with 1 second timeout between attempts.
Set to -1 for unlimited. Default 100.
Set to -1 for unlimited. Default 100.
api_key : str
MTA API key. If not provided, it will be read from the $MTA_API_KEY env
MTA API key. If not provided, it will be read from the $MTA_API_KEY env
variable.
return_dict : bool
Option to return the process data as a dict rather than as raw protobuf data.
This is equivalent to running ``load_protobuf(request_robust(...))``.
Returns
-------
bytes or dict
The current GTFS data as bytes or a dictionary, depending on the
The current GTFS data as bytes or a dictionary, depending on the
``return_dict`` flag.
"""
Expand All @@ -119,7 +119,6 @@ def request_robust(
break # break if success

except (EmptyFeedError, google.protobuf.message.DecodeError):

# raise if we're out of retries
if attempt == retries:
raise
Expand Down
Loading

0 comments on commit ff9e857

Please sign in to comment.