Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Data structure, standard creators, Nicaragua networks #99

Merged
merged 18 commits into from
Jan 24, 2018
Merged

Data structure, standard creators, Nicaragua networks #99

merged 18 commits into from
Jan 24, 2018

Conversation

pantierra
Copy link
Contributor

@pantierra pantierra commented Dec 14, 2017

This is a new pull request for the overhauled data structure, now with standard creators and Nicaragua config files that rely on these. It comes with a lot of wonderful work by @AltNico and @ialokim.

Following a request of @ialokim, I'm opening a PR already. It is meant to be subject for review by all people involved in osm2gtfs.

This PR addresses the following issues:

@pantierra
Copy link
Contributor Author

pantierra commented Dec 14, 2017

For your information: Currently the Estelí and Managua creators are included in this PR (two json files only). There are also separate PRs for these (#88 and #92). Before merging this in, if desired we can remove them from this PR. For the sake of testing I would just leave them here for now:

  • osm2gtfs -c osm2gtfs/creators/managua/managua.json
  • osm2gtfs -c osm2gtfs/creators/esteli/esteli.json

@grote
Copy link
Owner

grote commented Dec 14, 2017

Thanks for this PR!

If the two creators are just two json files, leave them in and close the other PRs for them.

@pantierra pantierra changed the title Data structure Data structure, standard creators, Nicaragua creators Dec 14, 2017
@pantierra pantierra changed the title Data structure, standard creators, Nicaragua creators Data structure, standard creators, Nicaragua networks Dec 14, 2017
Copy link
Contributor

@ialokim ialokim left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome work @AltNico and @xamanu, some little changes I noticed. I didn't review the custom creators as I'm not very familiar with them.

members = {}
for member in stop_area.members:
if (isinstance(member, overpy.RelationNode) and
member.role == "platform"):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't we also accept stop_position? And shouldn't we also accept platforms as ways?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes we should! But this is how it is implemented at the moment (in master), and I would rather change this in a subsequent step (separate PR).

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, please no unrelated changes. This PR is too big as it is already. Changes in existing functionality should be made in separate PRs.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No worry, see #100.


"""
valid = False
if 'public_transport' in stop.tags:
if stop.tags['public_transport'] == 'platform':
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why don't we check for stop_position?

Copy link
Contributor Author

@pantierra pantierra Dec 14, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would say this is not the scope of this PR. It is how it is currently implemented (in master). Please, feel free to open up an issue for this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is treated in #100.

return True
elif 'amenity' in stop.tags:
valid = True
if 'amenity' in stop.tags:
if stop.tags['amenity'] == 'bus_station':
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All of this function seems to be very specific to buses, we should include cases for other public transport services too, such as railway=station, railway=tram_stop, ... (I'm sure there are a lot more)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I really see here a good point in what you are saying. But I think this should be the topic of a separate PR, as it is not directly connected to the scope of this here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Created #100.

osm_type = attr.ib(default="relation")
location_type = attr.ib(default=1)
osm_url = attr.ib(default="http://osm.org/" +
str(osm_type) + "/" + str(osm_id))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As in all the other cases, shouldn't we leave that one in __attrs_post_init__ (here duplicated). Plus: Is there any reason you never use https:// instead of http://?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I will change.

The reason for using http instead of https is, because when we started using the shorter link, the redirection was only working for http, but I checked and it seemed to be improved on OpenStreetMap.org, so we can perfectly switch here.


stop_id = attr.ib("")
location_type = attr.ib(default=0)
osm_url = attr.ib(default=None)
Copy link
Contributor

@ialokim ialokim Dec 14, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why don't we use an abstract osm-item class with osm_id, tags, name, osm_url and inherit the classes Station, Stop, Itinerary and Line? Or eventually another parent grouping for the first and latter two? Is this possible in combination with attrs?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That would be also helpful for the _attrs_post_init__ methods.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a good idea. We should check.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've seen that the former classes already had inheritance from BaseRoute, at least.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, thanks for the suggestions. Based on this, I did:

  • Made all existing data elements Line, Itinerary, Station and Stop inheriting the basic attributes from a new class Element.
  • Moved add data elements into elements.py

times = trip["times"]

if times is None:
print("Warning: Couldn't load times from schedule for route")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

print the route_id and the service string for debugging

Copy link
Contributor Author

@pantierra pantierra Dec 16, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The route_id is printed already in the main function add_trips_to_feed and on the screen the information is present together. The service string is a long list of time information, not sure if this would be nice to print.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, perfect ! :)

trip_services = trip["services"]
if (trip[
"from"] == itinerary.fr and trip[
"to"] == itinerary.to and service in trip_services):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here, via tag

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See #101.

hex_color = '000000'
elif color == u'blue':
hex_color = '0000FF'
elif color == u'gray':
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could support grey here too, couln't we?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed to webcolors. (i hope) they do everything with a magical name_to_hex function.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually I had some thoughts about the whole part of colors. And it turns out to be specific. Now, only Estelí is using it and especially the complementary color function I am not very convinced that it is mature to get into the "Core". So, I moved it to a newly created routes_creator_esteli.py.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if this has to be specific. At least for Managua, the same approach can be used. It is very common to tag a route with the colour tag, see the OSM-Wiki.

What exactly are your concerns about the complementary color computation?

Copy link
Contributor Author

@pantierra pantierra Dec 16, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, the colour tag from OpenSrreetMap is supported and for example Managua uses it, too (using hex values as they are also specified on OSM for the colour tag). I just suggested to move two things to the Estelí creator:

  • conversion from name to hex: about the introduced function to map names and hex I was not convinced, so I thought webcolors was a good idea. But it is another dependency and I'm not sure really most creators may use it. Currently it is only Estelí. @grote suggested to do this in a separate issue.
  • generation of a complementary color: first it wasn't working... The result was always #000000. Then I checked it briefly, and realized that I'm doubting the "complementary" color is what we need. I think we need more the color with the highest contrast, which seems to be something different. I think it is not that easy than the function proposes and I would prefer to handle it also in a new issue.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I opened up an issue to discuss this: #104

else:
rv = result.get_relations(member.ref)
if bool(rv):
rv = rv.pop()
sys.stderr.write("Route variant was assigned again:\n")
sys.stderr.write("Itinerary was assigned again:\n")
sys.stderr.write(
"http://osm.org/relation/" + str(rv.id) + "\n")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here and in all the other cases, we should use an static variable to not hardcode the same url over and over again? Also, please use https.

Copy link
Contributor Author

@pantierra pantierra Dec 14, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed to https. However on using a static variable or a global constant and how to handle those concepts in Python is not completely clear to me. A quick research got me to the point, that we probably will need some kind of const class, which will bring a lot of good oportunities. But it seems to be bigger and we need to think about it. What about doing this in a separate issue? So far they have always been hardcoded, so maybe let's change it properly after this going in. What do you think, @ialokim?

Copy link
Contributor

@ialokim ialokim Dec 14, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm okay with this. 👍 Could you open the new issue?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, #102.

"http://osm.org/" + self.osm_type + "/" + str(
self.osm_id) + "\n")
sys.stderr.write("http://osm.org/" + identifier + "\n")
sys.stderr.write("http://osm.org/" + self._parent_station + "\n")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use osm_url here and above.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not possible, because we are not getting full objects, but rather the parent station is the GTFS stop_id, which people likely want to override in their stops_creator. Given this I think the error messages leading to OSM objects, are not a good idea here. Taking them out.

Copy link
Collaborator

@AltNico AltNico left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work, @xamanu, you have improved the code I've originally written a lot with these changes. I agree with @ialokim comments and have not reviewed custom creators nor ran this pull request.

return center_lat, center_lon

@staticmethod
def get_hex_code_for_color(color):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's already a pretty extensive list but I think we should at least support the colors mentioned in the OSM wiki.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would replace it with webcolors

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Like that idea! Should it be another PR?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, the whole color transformation (from name to hex; from one color to a high contrast color) is probably better to handle separately: #104

# Collect the Stop objects that are members
# of this Station
members["node/" + str(member.ref)] = self.stops[
'regular']["node/" + str(member.ref)]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could create a variable for "node/" + str(member.ref) to not build it three times.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or even three static variables for the three osm types?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See related #102.

variants of the same service line.

In OpenStreetMap this is usually represented as "route_master" relation.
In GTFS this is usually represented as "route"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sentence should end with a . like the other ones.

from math import cos, sin, atan2, sqrt, radians, degrees


class Helper(object):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great idea with the Helper class!

# Related route variants
_itineraries = attr.ib(default=attr.Factory(list))

def __attrs_post_init__(self):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great idea with this __attrs_post_init__!

def add_stops_to_routes(self, data):
routes = data.routes
stops = data.stops
if type(stop_name).__name__ == "unicode":
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unicode handling in Python (2) is so ugly...


if "gtfs_stop_id" in stop.tags:
# Use a GTFS stop_id coming from OpenStreetMap data
return stop.tags['gtfs_stop_id']
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the usage of gtfs_stop_id in OpenStreetMap documented?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, it is not. If people here are very strong on taking it out. I'm fine with it. I just think it is a nice feature, especially when GTFS already exist in an area and the stops should map to those ids.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see the use cases for defining their own stop IDs, but if someone needs it, I'm fine with it. At least I would document it somewhere in the osm2gtfs wiki.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In Grande Vitória, most bus stops have a ref defined by municipal or operator, usually posted on the bus stop sign, all known such references are mapped with the ref tag. This could be used instead of automatically get the OSM object ID. Making an independent gifts_stop_id tag will only duplicate data and result in data not being added.

Copy link
Contributor Author

@pantierra pantierra Dec 15, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Most people who work with GTFS appear to be kind of holy about their ids (think about porting an existing GTFS to OSM and then being able to see what's happening), and I can understand, because it is the reference to the thing. Yes, @Skippern, ref seems to be the correct way to go, maybe even also supportin ref:gtfs for special needs. gtfs_stop_id was a bad idea. Thanks for noticing, will change!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed, accordingly.

'stops': scheduled_stops, 'schedule': trips_schedule})
return trips

def _verify_data(self, schedule, line, itinerary):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great method that you've introduced here!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks 😄

try:
gtfs_trip.AddStopTime(gtfs_stop)
except ValueError:
print("Warning: Could not add a stop to trip.")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I remember correctly transitfeed only throws this ValueError when you try to add the first stop of a trip without time. We could adjust the message to include that information.

gtfs_service = ServicePeriod(service)
gtfs_service.SetDateHasService(service)
else:
raise KeyError("Unknown service keyword: " + service)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't this should also handle range of ISO dates like specified in the wiki?

Copy link
Contributor Author

@pantierra pantierra Dec 14, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@AltNico, Do you think this is a better to be handled in a new issue? Or should it be treated here?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think a new issue would be better.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done #103.

README.md Outdated
* [Florianópolis, Brazil](https://github.com/grote/osm2gtfs/blob/master/osm2gtfs/creators/fenix/fenix.json)
* [Suburban trains in Costa Rica](https://github.com/grote/osm2gtfs/blob/master/osm2gtfs/creators/incofer/incofer.json)
* [Accra, Ghana](https://github.com/grote/osm2gtfs/blob/master/osm2gtfs/creators/accra/accra.json)
* [Managua, Ciudad Sandino](https://github.com/grote/osm2gtfs/blob/master/osm2gtfs/creators/managua/managua.json) and [Estelí](https://github.com/grote/osm2gtfs/blob/master/osm2gtfs/creators/esteli/esteli.json) in Nicaragua
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Better to use relative links here. I think the wiki links above are fine absolute, but these here refer to files in the repo, so they should be relative.

members = {}
for member in stop_area.members:
if (isinstance(member, overpy.RelationNode) and
member.role == "platform"):
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, please no unrelated changes. This PR is too big as it is already. Changes in existing functionality should be made in separate PRs.

@ialokim
Copy link
Contributor

ialokim commented Dec 15, 2017

I've fixed two bugs found while generating the (almost complete now) GTFS for Esteli:

  • for __attrs_post_init__() used by the new Routes.py and Stops.py, version 17.1.0 is required (see the changelog)
  • the return object of urlopen can only be read once

@pantierra
Copy link
Contributor Author

pantierra commented Dec 15, 2017

Thanks, @ialokim! Glad to hear that the Estelí GTFS is reaching completeness. Looking forward to have public transport routing in Nicaragua for the first time and already in three cities! Yeay

@pantierra
Copy link
Contributor Author

pantierra commented Dec 16, 2017

Thanks for all the feedback so far! I think I processed all of it and made sure all networks build properly. In case you have already tested this PR, please make sure you execute (once) with the --refresh-all command line argument.

You should be easily able to build all networks, without preparing anything, just run:

  • osm2gtfs -c osm2gtfs/creators/fenix/fenix.json --refresh-all
  • osm2gtfs -c osm2gtfs/creators/incofer/incofer.json --refresh-all
  • osm2gtfs -c osm2gtfs/creators/accra/accra.json --refresh-all
  • osm2gtfs -c osm2gtfs/creators/esteli/esteli.json --refresh-all
  • osm2gtfs -c osm2gtfs/creators/managua/managua.json --refresh-all

Thanks everybody.

Copy link
Collaborator

@nlehuby nlehuby left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 very good job

self.route_color = self.tags['colour']

# pylint: disable=unsupported-membership-test,unsubscriptable-object
if 'ref:colour_tx' in self.tags:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ref:colour_tx is not a standard tag (I've never heard of this one before today ;) ), you will not find it in every route_master relations: it should be handled in the creators (just like the travel_time and frequency tags used in Accra.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also haven't heard about ref:colour_tx before 😄 Looking in the wiki I found it the other day and thought it would be probably the most appropriate. Yes, I agree, it can also be handled in the routes_creator.py, this is also totally fine.

elif 'route' in self.tags:
self.route_type = self.tags['route'].capitalize()
else:
self.route_type = "Bus"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should add a log for the route_master relations that do not have route_master tag: this is an issue that should be fixed in OSM.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, makes sense. Added.

a Line object.

In OpenStreetMap this is usually represented as "route" relation.
In GTFS this is not exlicitly presented but used as based to create "trips"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

exlicitly ? used as based ? :bowtie:

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, for noticing!

self.to = self.tags['to']

# pylint: disable=unsupported-membership-test,unsubscriptable-object
if 'duration' in self.tags:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

duration is not a standard tag you will find in all route_master relations: it should be handled in the creators (just like the travel_time and frequency tags used in Accra.

Copy link
Contributor Author

@pantierra pantierra Dec 16, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

duration is IMHO the standard tag. Ah, and if it is not defined on OSM, it will just fall back to None on the data object, and can and might be handled later in the creators as you suggest.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The more I think through it the more I follow your approach. Mainly because there has been so many different and valid ideas on how to handle it: travel_time or duration tag in OSM. In the other issue they also requested to define this in the schedule source. So, yes, will move it to the schedule creators. Thanks for rising it.

This function adds the routes from the data to the GTFS feed.
"""
# Get route information
routes = data.get_routes()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is unclear if we are talking about OSM routes or GTFS routes. Shouldn't we call this var lines instead of routes ?

Copy link
Contributor Author

@pantierra pantierra Dec 16, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually they contain both Lines (OSM Route Masters) and Itineraries (OSM Routes), when they appear together in code they are just called routes (like in the concept of GTFS).

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As I understand correctly, this variable only contains Lines objects containing Itineraries objects. Wouldn't it be easier to understand by making this explicit with a lines variable ?


def _define_route_color(self, route):
"""
Returns the route_route_color for the use in the GTFS feed.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So many route :bowtie:

# Send stop_id creation through overridable function
gtfs_stop_id = self._define_stop_id(stop)

# Save defined stop_id to the object for furhter use in other creators
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

furhter :bowtie:

times = None
for trip in schedule['lines'][itinerary.route_id]:
trip_services = trip["services"]
if (trip[
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Odd place to break the line 🤔 Why not ?

if (trip['from'] == itinerary.fr 
           and trip['to'] == itinerary.to 
            and service in trip_services):

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because my linter complains. Is it just mine? or I can do as you say? Which would be much nicer, indeed!

Copy link
Contributor Author

@pantierra pantierra Dec 16, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just tried with your proposal and unfortunately fails here in the CI, too:

osm2gtfs/creators/trips_creator.py:319:17: E129 visually indented line with same indent as next logical line

Please help me to produce a nicer readable line that sticks to our coding standards. The one in code was the only one that worked for me, without breaking the CI.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one seems ok :

            if (trip["from"] == itinerary.fr and
                    trip["to"] == itinerary.to and
                    service in trip_services):
                times = trip["times"]

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hey, yes @nlehuby this works and is much better. Thanks!

@pantierra
Copy link
Contributor Author

pantierra commented Dec 16, 2017

Thank you, @nlehuby!

Copy link
Collaborator

@AltNico AltNico left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully build a GTFS locally, thanks a lot! The output is already really clean and much more ordered than before!

Copy link
Contributor

@ialokim ialokim left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've done a second round and there are only two things I came up with: see here and here.

I think this is very close to perfect, thanks all!

@pantierra
Copy link
Contributor Author

Checks fail now, but is not caused by this Pull Request. Compare the same latest commit to upstream with exactly the identical recently pushed to another repository. Locally all tests work fine. No idea how to fix it.

"Error: Station with no members has been discarted:\n")
sys.stderr.write("https://osm.org/relation/" +
str(stop_area.id) + "\n")
return False
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method is sometimes returning None and sometimes False. This should be unified.

sys.stderr.write(
"Itinerary (" + itinerary.route_url + ") misses a stop: \n")
sys.stderr.write(
"Please review:" + itinerary_stop_id + "\n")
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

space after colon?

@pantierra
Copy link
Contributor Author

pantierra commented Jan 24, 2018

I went over the code again, rebased in on upstream's master and included suggestions and comments; also the "real problem" should be fixed by now. I would be happy to merge the current state in.

@grote
Copy link
Owner

grote commented Jan 24, 2018

Thanks for making the fixes so quickly. Looks good to me now. However, we shouldn't merge this as long as the CI is failing. It seems the problem is here:

Validation of stop_times.txt size : size1=458830 size2=470192

So the size of stop_times changed. Unfortunately, this is not very helpful in inspecting the differences. Maybe we can run diffoscope on it? The change might also come from today's transitfeed release. @xamanu can you try upgrading this locally and see if you can reproduce?

@grote
Copy link
Owner

grote commented Jan 24, 2018

Ok, CI is failing on master anyway, most likely due to the new transitfeed library.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants