impuls.model¶
- class impuls.model.Entity(*args, **kwargs)¶
Bases:
ProtocolEntity is a protocol for marshalling data between model entities and SQL and GTFS. Every entity defined in the model implements this protocol.
- static sql_columns() LiteralString¶
sql_columns returns a “(col1, col2, col3)” string used in SQL queries for this type. The number of question marks must match the number of elements returned by
sql_marshall().
- static sql_create_table() LiteralString¶
sql_create_table returns the SQL CREATE TABLE statement necessary to hold entities of this type.
- sql_marshall() tuple[None | int | float | str, ...]¶
sql_marshall converts an entity into its SQL representation.
- static sql_placeholder() LiteralString¶
sql_placeholder returns a “(?, ?, ?, ?, …)” string used in SQL queries for this type. The number of question marks must match the number of elements returned by
sql_marshall().
- sql_primary_key() tuple[None | int | float | str, ...]¶
sql_primary_key converts the primary key of an entity into its SQL representation. The returned tuple should have the same number of elements as
sql_where_clause()has parameters.
- static sql_set_clause() LiteralString¶
sql_set_clause returns a “COLUMN_NAME = ?, OTHER_COLUMN = ?, …” string used in UPDATE statements
- static sql_table_name() LiteralString¶
sql_table_name returns the SQL table name which holds entities of this type
- classmethod sql_unmarshall(row: Sequence[None | int | float | str]) Self¶
sql_unmarshall creates an entity from its SQL representation.
- static sql_where_clause() LiteralString¶
sql_where_clause returns a “COLUMN_NAME = ? AND …” string used in SQL queries to uniquely identify entities of this type.
- final class impuls.model.Agency(id: str, name: str, url: str, timezone: str, lang: str = '', phone: str = '', fare_url: str = '', extra_fields_json: str | None = None)¶
Bases:
Entity,ExtraFieldsMixinAgency represents the entity/public body/company responsible for high-level management (especially fares) of a public transportation network.
The exact meaning is up to the user, but an Agency should be the body riders associate as responsible for the transit system. For example, in Poland, for publicly run city networks this should be the city-run public transport authority (the organizer, e.g. Zarząd Transportu Miejskiego), but for train networks this should be the train company itself (e.g. Koleje Mazowieckie, even though technically the organizer is usually the voivodeship marshal).
Equivalent to GTFS’s agency.txt entries.
- extra_fields_json: str | None = None¶
- fare_url: str = ''¶
- id: str¶
- lang: str = ''¶
- name: str¶
- phone: str = ''¶
- timezone: str¶
- url: str¶
- final class impuls.model.Attribution(id: str, organization_name: str, is_producer: bool = False, is_operator: bool = False, is_authority: bool = False, is_data_source: bool = False, url: str = '', email: str = '', phone: str = '', extra_fields_json: str | None = None)¶
Bases:
Entity,ExtraFieldsMixinAttribution represents a copyright or any other attribution which must be attached to the dataset.
Equivalent to GTFS’s attributions.txt entries.
- email: str = ''¶
- extra_fields_json: str | None = None¶
- id: str¶
- is_authority: bool = False¶
- is_data_source: bool = False¶
- is_operator: bool = False¶
- is_producer: bool = False¶
- organization_name: str¶
- phone: str = ''¶
- url: str = ''¶
- final class impuls.model.Calendar(id: str, monday: bool = False, tuesday: bool = False, wednesday: bool = False, thursday: bool = False, friday: bool = False, saturday: bool = False, sunday: bool = False, start_date: Date = Date(1111, 11, 11), end_date: Date = Date(1111, 11, 11), desc: str = '', extra_fields_json: str | None = None)¶
Bases:
Entity,ExtraFieldsMixinCalendar defines a set of dates on which
Tripinstances operate.Equivalent to GTFS’s calendar.txt entries.
Contrary to GTFS, Calendar entries are mandatory, even if all operating dates are defined using
CalendarExceptioninstances. If this is the case, all weekdays should be set toFalseandstart_dateandend_dateshould be set toDate.SIGNALS_EXCEPTIONS.- compute_active_dates() set[Date]¶
Computes the set of active dates of this Calendar, not taking exceptions into account.
Use
CalendarException.reflect_in_active_dates()to takeCalendarExceptioninstances into account.
- property compressed_weekdays: int¶
- desc: str = ''¶
- extra_fields_json: str | None = None¶
- friday: bool = False¶
- id: str¶
- monday: bool = False¶
- saturday: bool = False¶
- sunday: bool = False¶
- thursday: bool = False¶
- tuesday: bool = False¶
- wednesday: bool = False¶
- final class impuls.model.CalendarException(calendar_id: str, date: Date, exception_type: Type)¶
Bases:
EntityCalendarExceptions are used to override operating dates defined by a
Calendar.Equivalent to GTFS’s calendar_dates.txt entries.
Contrary to GTFS,
Calendarentries are mandatory (even if empty), ascalendar_idis always a foreign key referencingCalendar.id.- static reflect_in_active_dates(active_dates: set[Date], exceptions: Iterable[CalendarException]) set[Date]¶
Reflects a set of CalendarExceptions in a set of active dates. Warning! The provided set is both modified in-place and later returned.
The set of active dates can come from Calendar.compute_active_dates.
- calendar_id: str¶
- class impuls.model.Date¶
Bases:
dateDate is an extension of datetime.date to represent dates of the Impuls model.
The extension provides
__str__andfrom_ymd_str()methods to convert between dates and YYYY-MM-DD strings, and a few other helper functions.- add_days(delta: int) Self¶
Returns a new day
deltadays off from self. Delta may be negative.>>> Date(2012, 6, 1).add_days(4) Date(2012, 6, 5) >>> Date(2012, 12, 27).add_days(7) Date(2013, 1, 3) >>> Date(2012, 2, 28).add_days(1) Date(2012, 2, 29) >>> Date(2013, 2, 28).add_days(1) Date(2013, 3, 1)
- classmethod from_ymd_str(x: str) Self¶
Parses a YYYY-MM-DD string into a Date. The separator may be omitted, or may be any non-word characters.
>>> Date.from_ymd_str("2012-06-01") Date(2012, 6, 1) >>> Date.from_ymd_str("20120825") Date(2012, 8, 25) >>> Date.from_ymd_str("2012.02.29") Date(2012, 2, 29)
- SIGNALS_EXCEPTIONS: ClassVar[Date] = Date(1111, 11, 11)¶
A placeholder Date used in
Calendarto indicate that this calendar is defined exclusively usingCalendarExceptioninstances. In principle, this could be any date, but onlySIGNALS_EXCEPTIONSis identified by theSaveGTFStask.
- class impuls.model.ExtraFieldsMixin¶
Bases:
objectExtraFieldsMixin provides helper methods for objects with a
extra_fields_jsonOptional[str]fields.- get_extra_field(field: str) str | None¶
get_extra_fields returns a specific of extra field stored in
extra_fields_json.Invoking this function causes an unconditional parse of
extra_fields_json, which may cause a small performance penalty. Useget_extra_fields()once to avoid parsing overhead.
- get_extra_fields() dict[str, str]¶
get_extra_fields returns a dictionary of all extra fields stored in
extra_fields_json.
- set_extra_field(field: str, value: str | None) None¶
set_extra_field sets a specific of extra field stored in
extra_fields_json.Invoking this function causes an unconditional parse and serialization of
extra_fields_json. Useget_extra_fields()andset_extra_fields()once to avoid JSON serialization overhead.
- set_extra_fields(extra_fields: Mapping[str, str] | None) None¶
get_extra_fields sets the extra fields stored in
extra_fields_jsonto the provided mapping.
- extra_fields_json: str | None¶
- final class impuls.model.ExtraTableRow(id: int, table_name: str, fields_json: str = '{}', row_sort_order: int | None = None)¶
Bases:
EntityExtraTableRow is a special
Entitywhich allows defining extra tables and their rows in a generic way.Note that by default,
LoadGTFSdoes not load unknown tables and columns.- get_field(field: str) str | None¶
get_field returns a specific field stored in
fields_json.Invoking this function causes an unconditional parse of
fields_json, which, if called repeatedly, may incur a performance penalty. Useget_fields()to avoid parsing overhead.
- get_fields() dict[str, str]¶
get_fields returns a fresh dictionary of all fields stored in the
fields_json.
- set_field(field: str, value: str | None) None¶
set_field sets a specific field stored in
extra_fields_json.Invoking this function causes an unconditional parse and serialization of
fields_json. Useget_fields()andset_fields()once to avoid JSON serialization overhead.
- set_fields(fields: Mapping[str, str]) None¶
set_fields sets all fields in
fields_jsonfrom the provided mapping.
- fields_json: str = '{}'¶
- id: int¶
This field is ignored on
DBConnection.create()- SQLite automatically generates an ID.
- row_sort_order: int | None = None¶
- table_name: str¶
- final class impuls.model.FareAttribute(id: str, price: float, currency_type: str, payment_method: PaymentMethod, transfers: int | None, agency_id: str, transfer_duration: int | None = None, extra_fields_json: str | None = None)¶
Bases:
Entity,ExtraFieldsMixinFareAttributes define a single logical fare class. Due to the way
FareRuleis applied, there may be multiple FareAttributes representing the same “ticket”.Equivalent to GTFS’s fare_attributes.txt entries.
- agency_id: str¶
- currency_type: str¶
- extra_fields_json: str | None = None¶
- id: str¶
- payment_method: PaymentMethod¶
- price: float¶
- transfer_duration: int | None = None¶
- transfers: int | None¶
- final class impuls.model.FareRule(fare_id: str, route_id: str = '', origin_id: str = '', destination_id: str = '', contains_id: str = '', id: int = 0)¶
Bases:
EntityFareRule instances restrict how
FareAttributeinstances can be applied.Equivalent to GTFS’s fare_rules.txt entries.
The GTFS specification is heavily vague on how multiple rules are combined. Impuls’s author current understanding is that: rules with different
route_idare logically ORed, while all rules with the sameroute_idare logically ANDed, both horizontally (across multiple rules) and vertically (across multiple fields). For example, the following rules:FareRule("f", route_id="", contains_id="A")FareRule("f", route_id="100", contains_id="A")FareRule("f", route_id="100", contains_id="B")FareRule("f", route_id="200", origin_id="A", destination_id="B")
Would be mean that fare
fapplies to (all routes if journey is completely within zoneA) OR (route100if journey passes exactly through zonesAandB) OR (route200if journey starts in zoneAand ends in zoneB(regardless if it passes through other zones)).Thus, fare
fwould apply to journeys on route100contained within zoneA(thanks to rule 1) or contained within zonesAandB(thanks to rules 2 and 3), but not within zoneB(as rules 2 and 3 are logically ANDed). Similarly, farefwould apply on journeys on route200contained within zoneA(thanks to rule 1); starting in zoneA, passing through zoneCand ending in zoneB(thanks to rule 4); but not starting in zoneBand ending in zoneA(as rule 4 is directional).Essentially,
origin_idanddestination_idapplied to theStop.zone_idof the embarking and disembarking stops of a user’s journey leg; whilecontains_idapplies to allStop.zone_idbetween the embarking and disembarking stops, inclusive.- contains_id: str = ''¶
- destination_id: str = ''¶
- fare_id: str¶
- id: int = 0¶
This field is ignored on
DBConnection.create()- SQLite automatically generates an ID.The GTFS primary key clause is incompatible with SQL, as it contains optional columns (in SQL PRIMARY KEY implies NOT NULL) - hence the need for a separate ID.
- origin_id: str = ''¶
- route_id: str = ''¶
- final class impuls.model.FeedInfo(publisher_name: str, publisher_url: str, lang: str, version: str = '', contact_email: str = '', contact_url: str = '', start_date: Date | None = None, end_date: Date | None = None, extra_fields_json: str | None = None, id: int = 0)¶
Bases:
Entity,ExtraFieldsMixinFeedInfo describes metadata about the schedule dataset.
Equivalent to GTFS’s feed_info.txt.
- contact_email: str = ''¶
- contact_url: str = ''¶
- extra_fields_json: str | None = None¶
- id: int = 0¶
id of the FeedInfo must be always 0, as there can only be at most one entry in the feed_info table.
- lang: str¶
- publisher_name: str¶
- publisher_url: str¶
- version: str = ''¶
- final class impuls.model.Frequency(trip_id: str, start_time: TimePoint, end_time: TimePoint, headway: int, exact_times: bool = False, extra_fields_json: str | None = None)¶
Bases:
Entity,ExtraFieldsMixinFrequency instances provide an alternative way of defining multiple trips in bulk. When a
Triphas at least oneFrequency, that tripsStopTimeabsolute times are ignored, instead multiple trips using the relative time differences are used as a pattern for multiple trips following the same pattern.Equivalent to GTFS’s frequencies.txt entries.
- exact_times: bool = False¶
- extra_fields_json: str | None = None¶
- headway: int¶
- trip_id: str¶
- final class impuls.model.Route(id: str, agency_id: str, short_name: str, long_name: str, type: Type, color: str = '', text_color: str = '', sort_order: int | None = None, extra_fields_json: str | None = None)¶
Bases:
Entity,ExtraFieldsMixinRoute instances group multiple trips operated by one
Agencyunder a single, common identifier.The same as a “line”; not to be confused with a “shape” or a “pattern”. For example all U2 services in Berlin should be grouped under a single route with short_name “U2” and long_name “Pankow - Ruhleben”. For agencies where lines are not commonly used in passenger information, service types may be used instead (common use case for railway operators, e.g. PKP Intercity (Poland) should represent TLK, IC, EIC and EIP train categories as routes, and Korail (South Korea) should represent KTX, ITX, Nuriro, Mungunghwa and Saemeul train categories as routes). If there’s no real distinction of services operated by an agency (common use case for long-haul coaches), a single route with agency name is sufficient.
Equivalent to GTFS’s routes.txt entries.
- class Type(*values)¶
Bases:
IntEnum- BUS = 3¶
- CABLE_TRAM = 5¶
- FERRY = 4¶
- FUNICULAR = 7¶
- GONDOLA = 6¶
- METRO = 1¶
- MONORAIL = 12¶
- RAIL = 2¶
- TRAM = 0¶
- TROLLEYBUS = 11¶
- agency_id: str¶
- color: str = ''¶
- extra_fields_json: str | None = None¶
- id: str¶
- long_name: str¶
- short_name: str¶
- sort_order: int | None = None¶
- text_color: str = ''¶
- final class impuls.model.ShapePoint(shape_id: str, sequence: int, lat: float, lon: float, shape_dist_traveled: float | None = None)¶
Bases:
EntityShapePoints describe the real path a trip takes, used for plotting journeys on a map.
Equivalent to GTFS’s shapes.txt entries.
Note that in GTFS
shape_idis not a primary key in any table, rather, it’s a “virtual”, implied entity. In Impuls, this is not the case, a separateshapestable is present, with a sole primary key column,shape_id. There’s no corresponding entity for that table. Before inserting ShapePoints into a database, execute aINSERT INTO shapes (shape_id) VALUES (?)SQL statement.- lat: float¶
- lon: float¶
- sequence: int¶
- shape_dist_traveled: float | None = None¶
- shape_id: str¶
- final class impuls.model.Stop(id: str, name: str, lat: float, lon: float, code: str = '', zone_id: str = '', location_type: LocationType = LocationType.STOP, parent_station: str = '', wheelchair_boarding: bool | None = None, platform_code: str = '', extra_fields_json: str | None = None)¶
Bases:
Entity,ExtraFieldsMixinStop can represent 3 different point-like entities, depending on the
location_typevalue, usually physical stops.LocationType.STOPrepresent physical places where passengers can embark and disembark from vehicles.LocationType.STATIONrepresent a grouping of multiple stops and exits under a single physical structure. Note that two stops on an opposite side of a road do not form a station (as these do not form a single physical structure), but an underground bus terminus might. Stop-station structures should be only used when you want to provide exits, or different platform positions. If those details are not available, it is ok to provide single stops representing entire railway stations.LocationType.EXITrepresent an exit to a station.Equivalent to GTFS’s stops.txt entries.
- code: str = ''¶
- extra_fields_json: str | None = None¶
- id: str¶
- lat: float¶
- location_type: LocationType = 0¶
- lon: float¶
- name: str¶
- parent_station: str = ''¶
parent_station references
Stop.id, with empty string mapping to SQL NULL. Optional for stops, forbidden for stations and mandatory for exits.
- platform_code: str = ''¶
- wheelchair_boarding: bool | None = None¶
- zone_id: str = ''¶
- final class impuls.model.StopTime(trip_id: str, stop_id: str, stop_sequence: int, arrival_time: TimePoint, departure_time: TimePoint, pickup_type: PassengerExchange = PassengerExchange.SCHEDULED_STOP, drop_off_type: PassengerExchange = PassengerExchange.SCHEDULED_STOP, stop_headsign: str = '', shape_dist_traveled: float | None = None, platform: str = '', extra_fields_json: str | None = None)¶
Bases:
Entity,ExtraFieldsMixinStopTime represents a stoppage/passage of a
Tripat/through aStop.Equivalent to GTFS’s stop_times.txt entries.
- class PassengerExchange(*values)¶
Bases:
IntEnum- MUST_PHONE = 2¶
- NONE = 1¶
- ON_REQUEST = 3¶
- SCHEDULED_STOP = 0¶
- drop_off_type: PassengerExchange = 0¶
- extra_fields_json: str | None = None¶
- pickup_type: PassengerExchange = 0¶
- platform: str = ''¶
- shape_dist_traveled: float | None = None¶
- stop_headsign: str = ''¶
- stop_sequence: int¶
- trip_id: str¶
- class impuls.model.TimePoint¶
Bases:
timedeltaTimePoint is an extension of datetime.timedelta to represent seconds since noon minus 12 hours.
The extension only provides
__str__andfrom_str()methods to help with conversion between TimePoints and HH:MM:SS strings.- classmethod from_str(x: str) Self¶
Parses a TimePoint from a HH:MM:SS strings
>>> TimePoint.from_str("8:30:00").total_seconds() 30600.0 >>> TimePoint.from_str("08:30:00").total_seconds() 30600.0 >>> TimePoint.from_str("25:01:08").total_seconds() 90068.0
- final class impuls.model.Transfer(from_stop_id: str = '', to_stop_id: str = '', from_route_id: str = '', to_route_id: str = '', from_trip_id: str = '', to_trip_id: str = '', type: Type = Type.RECOMMENDED, min_transfer_time: int | None = None, extra_fields_json: str | None = None, id: int = 0)¶
Bases:
Entity,ExtraFieldsMixinTransfer represent special rules for transferring between vehicles on the network.
Equivalent to GTFS’s transfers.txt entries.
- class Type(*values)¶
Bases:
IntEnum- IMPOSSIBLE = 3¶
- IN_SEAT = 4¶
- MIN_TIME_REQUIRED = 2¶
- RECOMMENDED = 0¶
- RE_BOARD = 5¶
- TIMED = 1¶
- extra_fields_json: str | None = None¶
- from_route_id: str = ''¶
- from_stop_id: str = ''¶
- from_trip_id: str = ''¶
- id: int = 0¶
This field is ignored on
DBConnection.create()- SQLite automatically generates an ID.The GTFS primary key clause is incompatible with SQL, as it contains optional columns (in SQL PRIMARY KEY implies NOT NULL) - hence the need for a separate ID.
- min_transfer_time: int | None = None¶
- to_route_id: str = ''¶
- to_stop_id: str = ''¶
- to_trip_id: str = ''¶
- final class impuls.model.Translation(table_name: Literal['agency', 'stops', 'routes', 'trips', 'stop_times', 'feed_info', 'attributions'], field_name: str, language: str, translation: str, record_id: str = '', record_sub_id: str = '', field_value: str = '', extra_fields_json: str | None = None, id: int = 0)¶
Bases:
Entity,ExtraFieldsMixinTranslation instances provide a way to translate user-facing text, URLs, emails and phone numbers in consumer apps to better serve multi-lingual regions or regions where some riders are not expected to be able to understand and read the local language.
Equivalent to GTFS’s translations.txt entries.
record_idandfield_valuemust not be provided simultaneously. Ifrecord_sub_idis not empty,record_idmust not be empty as well.Translation entities are copied as-is to and from GTFS, and thus all of the selectors must use their GTFS equivalents. Due to the very generic nature of these entities, not all requirements are strictly enforced.
- extra_fields_json: str | None = None¶
- field_name: str¶
field_name defines the GTFS column name for which the translation applies. For example, to translate
Trip.headsign,table_namemust be set totripsandfield_namemust be set totrip_headsign.
- field_value: str = ''¶
The original string to be translated.
An alternative way to select strings to be translated is through the
record_idattribute. Exactly one of field_value orrecord_idmust be defined - both fields can’t be empty and both fields can be simultaneously non-empty.
- id: int = 0¶
This field is ignored on
impuls.DBConnection.create()- SQLite automatically generates an ID.The GTFS primary key clause is incompatible with SQL, as it contains optional columns (in SQL PRIMARY KEY implies NOT NULL) - hence the need for a separate ID.
- language: str¶
An IETF language tag of the translated string.
- record_id: str = ''¶
Primary key to select the appropriate record from
table_name. This should be a reference to the following attributes, depending on the selected table:An alternative way to select strings to be translated is through the
field_valueattribute. Unless the selected table isfeed_info, exactly one offield_valueor record_id must be defined - both fields can’t be empty and both fields can be simultaneously non-empty.If the selected table is
stop_timesand record_id is not empty,record_sub_idmust also be non-empty.
- record_sub_id: str = ''¶
Secondary part of the primary key of the appropriate record from
table_name.This is only used for stop times, and must be a reference to
StopTime.stop_sequence. record_sub_id must not be used for any other tables or when usingfield_value.
- table_name: Literal['agency', 'stops', 'routes', 'trips', 'stop_times', 'feed_info', 'attributions']¶
table_name selects the GTFS table name of the entity type on which the translation applies:
- final class impuls.model.Trip(id: str, route_id: str, calendar_id: str, headsign: str = '', short_name: str = '', direction: Direction | None = None, block_id: str = '', shape_id: str = '', wheelchair_accessible: bool | None = None, bikes_allowed: bool | None = None, exceptional: bool | None = None, extra_fields_json: str | None = None)¶
Bases:
Entity,ExtraFieldsMixinTrips represent a single journey made by a vehicle, belonging to a specific
RouteandCalendar, grouping multipleStopTimeobjects.Equivalent to GTFS’s trips.txt entries.
- bikes_allowed: bool | None = None¶
- block_id: str = ''¶
block_id is used to group multiple trips where a rider can transfer without leaving a vehicle. This should only be used for circular routes or through service between routes; grouping multiple outbound and inbound trips (from a single diagram) of a single route with block_id provides no value to riders and creates visual confusion in consumer applications.
Empty string maps to SQL NULL.
- calendar_id: str¶
- exceptional: bool | None = None¶
- extra_fields_json: str | None = None¶
- headsign: str = ''¶
- id: str¶
- route_id: str¶
- shape_id: str = ''¶
shape_id references
Shape.id, with empty string mapping to SQL NULL.
- short_name: str = ''¶
- wheelchair_accessible: bool | None = None¶
- impuls.model.ALL_MODEL_ENTITIES: list[Type[Entity]] = [<class 'impuls.model.agency.Agency'>, <class 'impuls.model.attribution.Attribution'>, <class 'impuls.model.calendar.Calendar'>, <class 'impuls.model.calendar_exception.CalendarException'>, <class 'impuls.model.feed_info.FeedInfo'>, <class 'impuls.model.route.Route'>, <class 'impuls.model.stop.Stop'>, <class 'impuls.model.fare_attribute.FareAttribute'>, <class 'impuls.model.fare_rule.FareRule'>, <class 'impuls.model.shape_point.ShapePoint'>, <class 'impuls.model.trip.Trip'>, <class 'impuls.model.stop_time.StopTime'>, <class 'impuls.model.frequency.Frequency'>, <class 'impuls.model.transfer.Transfer'>, <class 'impuls.model.translation.Translation'>, <class 'impuls.model.extra_table_row.ExtraTableRow'>]¶
List of all
Entityclasses which belong to the Impuls data model. The list is ordered to allow marshalling without KEY violations, e.g.Tripis beforeStopTimeas the latter referencesTrip.id.