Skip to content

Commit

Permalink
Merge branch 'release/4.1.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
araichev committed Dec 18, 2024
2 parents 7a453b0 + 6116d15 commit 16a0f3f
Show file tree
Hide file tree
Showing 12 changed files with 2,670 additions and 4,075 deletions.
76 changes: 19 additions & 57 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -1,73 +1,35 @@
name: test
name: Test

on:
push:
branches: [master]
pull_request:
branches:
- master

jobs:
linting:
runs-on: ubuntu-latest
steps:
#----------------------------------------------
# check-out repo and set-up python
#----------------------------------------------
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
#----------------------------------------------
# load pip cache if cache exists
#----------------------------------------------
- uses: actions/cache@v3
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip
restore-keys: ${{ runner.os }}-pip
test:
needs: linting
runs-on: ubuntu-latest

strategy:
fail-fast: true
matrix:
os: [ "ubuntu-latest" ]
python-version: [ "3.9", "3.10", "3.11" ]
runs-on: ${{ matrix.os }}
python-version: ["3.10", "3.11", "3.12"]

steps:
#----------------------------------------------
# check-out repo and set-up python
#----------------------------------------------
- name: Check out repository
- name: Checkout code
uses: actions/checkout@v3
- name: Set up python ${{ matrix.python-version }}
id: setup-python

- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
#----------------------------------------------
# ----- install & configure poetry -----
#----------------------------------------------
- name: Install Poetry
uses: snok/install-poetry@v1
with:
virtualenvs-create: true
virtualenvs-in-project: true
# load cached venv if cache exists
#----------------------------------------------
- name: Load cached venv
id: cached-poetry-dependencies
uses: actions/cache@v3
with:
path: .venv
key: venv-${{ runner.os }}-${{ steps.setup-python.outputs.python-version }}-${{ hashFiles('**/poetry.lock') }}
#----------------------------------------------
# install dependencies if cache does not exist
#----------------------------------------------
- name: Install dependencies
if: steps.cached-poetry-dependencies.outputs.cache-hit != 'true'

- name: Install UV
run: |
poetry install --no-interaction --no-root --only main githubtest
#----------------------------------------------
# add matrix specifics and run test suite
#----------------------------------------------
curl -LsSf https://astral.sh/uv/install.sh | sh
- name: Sync project environment with UV
run: |
uv sync
- name: Run tests
run: |
source .venv/bin/activate
pytest -x
uv run pytest
11 changes: 4 additions & 7 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
repos:
- repo: https://github.com/kynan/nbstripout
rev: 0.7.1
rev: 0.8.1
hooks:
- id: nbstripout
files: ".ipynb"
- repo: https://github.com/psf/black
rev: 24.4.2
hooks:
- id: black
- repo: https://github.com/charliermarsh/ruff-pre-commit
# Ruff version.
rev: 'v0.5.1'
rev: 'v0.8.3'
hooks:
- id: ruff
- id: ruff
- id: ruff-format
2 changes: 0 additions & 2 deletions .pre-commit-hooks.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
- id: nbstripout
name: nbstripout
- id: black
name: black
- id: ruff
name: ruff
17 changes: 11 additions & 6 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ Make GTFS
***********
.. image:: https://github.com/mrcagney/gtfs_kit/actions/workflows/test.yml/badge.svg

A Python 3.9+ library to build GTFS feeds from basic route information.
A Python 3.10+ library to build GTFS feeds from basic route information.
Inspired by Conveyal's `geom2gtfs <https://github.com/conveyal/geom2gtfs>`_.
Makes naive timetables, but they are often good enough for preliminary work.

Expand All @@ -13,10 +13,8 @@ Contributors

Installation
=============
To use as a library in your own project (called something other than ``make_gtfs``), make a Python 3.9+ virtual environment for your project, then run ``poetry add make_gtfs``.

To develop the ``make_gtfs`` repo, Git clone it, make a Python 3.9+ virtual environment, then run ``poetry install --no-root && pre-commit install``.

To use as a library in your own project, install as a dependency with UV, say, via ``uv add make_gtfs``.
To develop the ``make_gtfs`` repo, Git clone it, then run ``uv add make_gtfs``.

Usage
=====
Expand Down Expand Up @@ -139,14 +137,21 @@ On Github pages `here <https://mrcagney.github.io/make_gtfs_docs>`_.
Notes
======
- This project's development status is Alpha.
Alex and Danielle use this project for work and change it breakingly when it suits their needs.
Alex uses this project for work and changes it breakingly when it suits his needs.
- This project uses semantic versioning.
- Thanks to `MRCagney <https://mrcagney.com>`_ for periodically funding this project.


Changes
========

4.1.0, 2024-12-19
-----------------
- Switched from Poetry to UV for project management.
- Bumped to Python 3.10+.
- Fixed some Pandas deprecation warnings.
- Fixed CLI access.

4.0.7, 2024-07-10
-----------------
- Updated dependencies.
Expand Down
2 changes: 1 addition & 1 deletion make_gtfs/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@
from .hashables import *
from .main import *

__version__ = "4.0.7"
__version__ = "4.1.0"
15 changes: 6 additions & 9 deletions make_gtfs/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
This module contains the main logic.
"""

from __future__ import annotations

from functools import lru_cache
import math

Expand Down Expand Up @@ -283,7 +281,7 @@ def build_stops(
# Keep only one line per antiparallel pair of shapes.
# These can be determined from the shape IDs.
shapes_g = (
gk.geometrize_shapes_0(shapes, use_utm=True)
gk.geometrize_shapes(shapes, use_utm=True)
.assign(base_shape=lambda x: x.shape_id.str.split(cs.SEP, expand=True)[0])
.drop_duplicates("base_shape")
)
Expand Down Expand Up @@ -451,8 +449,7 @@ def compute_shape_point_speeds(
return gpd.GeoDataFrame()

# Get UTM CRS to compute distances in metres
lat, lon = shapes[["shape_pt_lat", "shape_pt_lon"]].values[0]
utm_crs = gk.get_utm_crs(lat, lon)
utm_crs = speed_zones.estimate_utm_crs()
speed_zones = speed_zones.to_crs(utm_crs)

# Build shape points
Expand All @@ -471,13 +468,13 @@ def compute_dists(group):
.to_crs(utm_crs)
.sort_values(["shape_id", "shape_pt_sequence"])
.groupby("shape_id")
.apply(compute_dists)
.apply(compute_dists, include_groups=False)
.drop(["dist", "shape_pt_lat", "shape_pt_lon"], axis="columns")
)

# Get points where shapes intersect speed zone boundaries
shapes_g = (
gk.geometrize_shapes_0(shapes)
gk.geometrize_shapes(shapes)
.to_crs(utm_crs)
.assign(
boundary_points=lambda x: x.intersection(speed_zones.boundary, align=True)
Expand Down Expand Up @@ -672,8 +669,8 @@ def build_stop_times(
).merge(routes)

# Get the geometries of GTFS ``shapes``, not ``pfeed.shapes``
shapes_gi = gk.geometrize_shapes_0(shapes, use_utm=True).set_index("shape_id")
stops_g = gk.geometrize_stops_0(stops, use_utm=True)
shapes_gi = gk.geometrize_shapes(shapes, use_utm=True).set_index("shape_id")
stops_g = gk.geometrize_stops(stops, use_utm=True)

# For each trip get its shape and stops nearby and set stop times based on its
# service window frequency.
Expand Down
12 changes: 7 additions & 5 deletions make_gtfs/protofeed.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import pandas as pd
import numpy as np
import shapely.geometry as sg
import gtfs_kit as gk

from . import validators as vd
from . import constants as cs
Expand Down Expand Up @@ -102,7 +101,10 @@ def my_agg(group):
return pd.Series(d)

self.shapes_extra = dict(
self.frequencies.groupby("shape_id").apply(my_agg).reset_index().values
self.frequencies.groupby("shape_id")
.apply(my_agg, include_groups=False)
.reset_index()
.values
)

# Build service area as the bounding box of the shapes buffered by about 1 km
Expand All @@ -128,6 +130,7 @@ def my_agg(group):
else:

def my_apply(group):
group["route_type"] = group.name
return self.clean_speed_zones(
group,
service_area,
Expand All @@ -136,12 +139,11 @@ def my_apply(group):

self.speed_zones = (
self.speed_zones.groupby("route_type", group_keys=False)
.apply(my_apply)
.apply(my_apply, include_groups=False)
.filter(["route_type", "speed_zone_id", "speed", "geometry"])
)

lon, lat = self.shapes.geometry.iat[0].coords[0]
self.utm_crs = gk.get_utm_crs(lat, lon)
self.utm_crs = self.shapes.estimate_utm_crs()

def __eq__(self, other) -> bool:
for k in self.__dataclass_fields__:
Expand Down
Loading

0 comments on commit 16a0f3f

Please sign in to comment.