From 80ba00d0320867cc9f59903667dfa77107da2d50 Mon Sep 17 00:00:00 2001 From: Marc Garcia Puig Date: Thu, 25 Apr 2019 12:21:25 +0200 Subject: [PATCH] Improved PythonAPI docs generation --- Docs/python_api.md | 723 ++++---------------------------- PythonAPI/docs/client.yml | 3 +- PythonAPI/docs/doc_gen.py | 341 +++++++++++---- PythonAPI/docs/map.yml | 2 +- PythonAPI/docs/requirements.txt | 1 + 5 files changed, 358 insertions(+), 712 deletions(-) create mode 100644 PythonAPI/docs/requirements.txt diff --git a/Docs/python_api.md b/Docs/python_api.md index 1aaf8885d..4f139bcef 100644 --- a/Docs/python_api.md +++ b/Docs/python_api.md @@ -1,635 +1,88 @@ -

Python API Reference

- -!!! important - Versions prior to 0.9.0 have a very different API. For the documentation of - the stable version please switch to the - [stable branch](https://carla.readthedocs.io/en/stable/). - -## `carla.Client` - -- `Client(host, port, worker_threads=0)` -- `set_timeout(float_seconds)` -- `get_client_version()` -- `get_server_version()` -- `get_world()` -- `get_available_maps()` -- `reload_world()` -- `load_world(map_name)` -- `start_recorder(string filename)` -- `replay_file(string filename, float start, float duration, int camera_follow_id)` -- `show_recorder_file_info(string filename)` -- `show_recorder_collisions(string filename, char category1, char category2)` -- `show_recorder_actors_blocked(string filename, float min_time, float min_distance)` -- `set_replayer_speed(float time_factor)` -- `apply_batch(commands, do_tick=False)` -- `apply_batch_sync(commands, do_tick=False)` -> list(carla.command.Response) - -## `carla.World` - -- `id` -- `debug` -- `get_blueprint_library()` -- `get_map()` -- `get_spectator()` -- `get_settings()` -- `apply_settings(world_settings) -> int (id of the frame when the settings took effect)` -- `get_weather()` -- `set_weather(weather_parameters)` -- `get_snapshot() -> carla.WorldSnapshot` -- `get_actor(actor_id) -> carla.Actor` -- `get_actors(actor_ids=None) -> carla.ActorList` -- `spawn_actor(blueprint, transform, attach_to=None)` -- `try_spawn_actor(blueprint, transform, attach_to=None, attachment_type=carla.AttachmentType.Rigid)` -- `wait_for_tick(seconds=1.0) -> carla.WorldSnapshot` -- `on_tick(callback) -> id of the callback` -- `remove_on_tick(id)` -- `tick() -> int (id of the newly started frame)` - -## `carla.WorldSettings` - -- `synchronous_mode` -- `no_rendering_mode` -- `fixed_delta_seconds` -- `__eq__(other)` -- `__ne__(other)` - -## `carla.WorldSnapshot` - -- `id` -- `frame` -- `timestamp` -- `frame_count` _deprecated, use timestamp instead_ -- `elapsed_seconds` _deprecated, use timestamp instead_ -- `delta_seconds` _deprecated, use timestamp instead_ -- `platform_timestamp` _deprecated, use timestamp instead_ -- `has_actor(actor_id) -> bool` -- `find(actor_id) -> carla.ActorSnapshot` -- `__len()__` -- `__iter()__` -- `__eq(other)__` -- `__ne(other)__` - -## `carla.DebugHelper` - -- `draw_point(location, size=0.1, color=carla.Color(), life_time=-1.0, persistent_lines=True)` -- `draw_line(begin, end, thickness=0.1, color=carla.Color(), life_time=-1.0, persistent_lines=True)` -- `draw_arrow(begin, end, thickness=0.1, arrow_size=0.1, color=carla.Color(), life_time=-1.0, persistent_lines=True)` -- `draw_box(box, rotation, thickness=0.1, color=carla.Color(), life_time=-1.0, persistent_lines=True)` -- `draw_string(location, text, draw_shadow=False, color=carla.Color(), life_time=-1.0, persistent_lines=True)` - -## `carla.BlueprintLibrary` - -- `find(id)` -- `filter(wildcard_pattern)` -- `__getitem__(pos)` -- `__len__()` -- `__iter__()` - -## `carla.ActorBlueprint` - -- `id` -- `tags` -- `has_tag(tag)` -- `match_tags(wildcard_pattern)` -- `has_attribute(key)` -- `get_attribute(key)` -- `set_attribute(key, value)` -- `__len__()` -- `__iter__()` - -## `carla.ActorAttribute` - -- `id` -- `type` -- `recommended_values` -- `is_modifiable` -- `as_bool()` -- `as_int()` -- `as_float()` -- `as_str()` -- `as_color()` -- `__eq__(other)` -- `__ne__(other)` -- `__nonzero__()` -- `__bool__()` -- `__int__()` -- `__float__()` -- `__str__()` - -## `carla.ActorList` - -- `find(id)` -- `filter(wildcard_pattern)` -- `__getitem__(pos)` -- `__len__()` -- `__iter__()` - -## `carla.Actor` - -- `id` -- `type_id` -- `parent` -- `semantic_tags` -- `is_alive` -- `attributes` -- `get_world()` -- `get_location()` -- `get_transform()` -- `get_velocity()` -- `get_angular_velocity()` -- `get_acceleration()` -- `set_location(location)` -- `set_transform(transform)` -- `set_velocity(vector)` -- `set_angular_velocity(vector)` -- `add_impulse(vector)` -- `set_simulate_physics(enabled=True)` -- `destroy()` -- `__str__()` - -## `carla.ActorSnapshot` - -- `id` -- `get_location()` -- `get_transform()` -- `get_velocity()` -- `get_angular_velocity()` -- `get_acceleration()` -- `__str__()` - -## `carla.Vehicle(carla.Actor)` - -- `bounding_box` -- `apply_control(vehicle_control)` -- `get_control()` -- `get_physics_control()` -- `apply_physics_control(vehicle_physics_control)` -- `set_autopilot(enabled=True)` -- `get_speed_limit()` -- `get_traffic_light_state()` -- `is_at_traffic_light()` -- `get_traffic_light()` - -## `carla.TrafficSign(carla.Actor)` - -- `trigger_volume -> carla.BoundingBox` - -## `carla.TrafficLight(carla.TrafficSign)` - -- `state` -- `set_state(traffic_light_state)` -- `get_state()` -- `set_green_time(green_time)` -- `get_green_time()` -- `set_yellow_time(yellow_time)` -- `get_yellow_time()` -- `set_red_time(red_time)` -- `get_red_time()` -- `get_elapsed_time()` -- `freeze(True)` -- `is_frozen()` -- `get_pole_index()` -- `get_group_traffic_lights()` - -## `carla.Sensor(carla.Actor)` - -- `is_listening` -- `listen(callback_function)` -- `stop()` - -## `carla.SensorData` - -- `frame` -- `frame_number` _deprecated, use `frame` instead_ -- `timestamp` -- `transform` - -## `carla.Image(carla.SensorData)` - -- `width` -- `height` -- `fov` -- `raw_data` -- `convert(color_converter)` -- `save_to_disk(path, color_converter=None)` -- `__len__()` -- `__iter__()` -- `__getitem__(pos)` -- `__setitem__(pos, color)` - -## `carla.LidarMeasurement(carla.SensorData)` - -- `horizontal_angle` -- `channels` -- `raw_data` -- `get_point_count(channel)` -- `save_to_disk(path)` -- `__len__()` -- `__iter__()` -- `__getitem__(pos)` -- `__setitem__(pos, location)` - -## `carla.CollisionEvent(carla.SensorData)` - -- `actor` -- `other_actor` -- `normal_impulse` - -## `carla.LaneInvasionEvent(carla.SensorData)` - -- `actor` -- `crossed_lane_markings` - -## `carla.GnssEvent(carla.SensorData)` - -- `latitude` -- `longitude` -- `altitude` - -## `carla.ObstacleDetectionSensorEvent(carla.SensorData)` - -- `actor` -- `other_actor` -- `distance` - -## `carla.VehicleControl` - -- `throttle` -- `steer` -- `brake` -- `hand_brake` -- `reverse` -- `gear` -- `manual_gear_shift` -- `__eq__(other)` -- `__ne__(other)` - - -## `carla.WheelPhysicsControl` - -- `tire_friction` -- `damping_rate` -- `max_steer_angle` -- `radius` -- `max_brake_torque` -- `max_handbrake_torque` -- `position` -- `__eq__(other)` -- `__ne__(other)` - -## `carla.GearPhysicsControl` - -- `ratio` -- `down_ratio` -- `up_ratio` -- `__eq__(other)` -- `__ne__(other)` - -## `carla.VehiclePhysicsControl` - -- `torque_curve` -- `max_rpm` -- `moi` -- `damping_rate_full_throttle` -- `damping_rate_zero_throttle_clutch_engaged` -- `damping_rate_zero_throttle_clutch_disengaged` -- `use_gear_autobox` -- `gear_switch_time` -- `clutch_strength` -- `final_ratio` -- `forward_gears` -- `mass` -- `drag_coefficient` -- `center_of_mass` -- `steering_curve` -- `wheels` -- `__eq__(other)` -- `__ne__(other)` - -## `carla.WalkerControl` - -- `direction` -- `speed` -- `jump` -- `__eq__(other)` -- `__ne__(other)` - -## `carla.WalkerBoneControl` - -- `bone_transforms` - - -## `carla.Map` - -- `__init__(name, xodr_content)` -- `name` -- `get_spawn_points()` -- `get_waypoint(location, project_to_road=True, lane_type=carla.LaneType.Driving)` -- `get_topology()` -- `generate_waypoints(distance)` -- `transform_to_geolocation(location)` -- `to_opendrive()` -- `save_to_disk(path=self.name)` - -## `carla.LaneType` - -- `NONE` -- `Driving` -- `Stop` -- `Shoulder` -- `Biking` -- `Sidewalk` -- `Border` -- `Restricted` -- `Parking` -- `Bidirectional` -- `Median` -- `Special1` -- `Special2` -- `Special3` -- `RoadWorks` -- `Tram` -- `Rail` -- `Entry` -- `Exit` -- `OffRamp` -- `OnRamp` -- `Any` - -## `carla.LaneChange` - -- `NONE` -- `Right` -- `Left` -- `Both` - -## `carla.LaneMarkingColor` - -- `Standard = White` -- `Blue` -- `Green` -- `Red` -- `White` -- `Yellow` -- `Other` - -## `carla.LaneMarkingType` - -- `NONE` -- `Other` -- `Broken` -- `Solid` -- `SolidSolid` -- `SolidBroken` -- `BrokenSolid` -- `BrokenBroken` -- `BottsDots` -- `Grass` -- `Curb` - -## `carla.LaneMarking` - -- `type` -> carla.LaneMarking -- `color` -> carla.RoadMarkColor -- `lane_change` -> carla.LaneChange -- `width` - -## `carla.Waypoint` - -- `id` -- `transform` -- `is_intersection` _deprecated, use `is_junction` instead_ -- `is_junction` -- `lane_width` -- `road_id` -- `section_id` -- `lane_id` -- `junction_id` -- `s` -- `lane_change` -> carla.LaneChange -- `lane_type` -> carla.LaneType -- `right_lane_marking` -> carla.LaneMarking -- `left_lane_marking` -> carla.LaneMarking -- `next(distance)` -> list(carla.Waypoint) -- `get_right_lane()` -> carla.Waypoint -- `get_left_lane()` -> carla.Waypoint - -## `carla.WeatherParameters` - -- `cloudyness` -- `precipitation` -- `precipitation_deposits` -- `wind_intensity` -- `sun_azimuth_angle` -- `sun_altitude_angle` -- `__eq__(other)` -- `__ne__(other)` - -Static presets - -- `carla.WeatherParameters.Default` -- `carla.WeatherParameters.ClearNoon` -- `carla.WeatherParameters.CloudyNoon` -- `carla.WeatherParameters.WetNoon` -- `carla.WeatherParameters.WetCloudyNoon` -- `carla.WeatherParameters.MidRainyNoon` -- `carla.WeatherParameters.HardRainNoon` -- `carla.WeatherParameters.SoftRainNoon` -- `carla.WeatherParameters.ClearSunset` -- `carla.WeatherParameters.CloudySunset` -- `carla.WeatherParameters.WetSunset` -- `carla.WeatherParameters.WetCloudySunset` -- `carla.WeatherParameters.MidRainSunset` -- `carla.WeatherParameters.HardRainSunset` -- `carla.WeatherParameters.SoftRainSunset` - -## `carla.Vector2D` - -- `x` -- `y` -- `__add__(other)` -- `__sub__(other)` -- `__eq__(other)` -- `__ne__(other)` - -## `carla.Vector3D` - -- `x` -- `y` -- `z` -- `__add__(other)` -- `__sub__(other)` -- `__eq__(other)` -- `__ne__(other)` - -## `carla.Location` - -- `x` -- `y` -- `z` -- `distance(other)` -- `__add__(other)` -- `__sub__(other)` -- `__eq__(other)` -- `__ne__(other)` - -## `carla.GeoLocation` - -- `latitude` -- `longitude` -- `altitude` -- `__eq__(other)` -- `__ne__(other)` - -## `carla.Rotation` - -- `pitch` -- `yaw` -- `roll` -- `get_forward_vector()` -- `__eq__(other)` -- `__ne__(other)` - -## `carla.Transform` - -- `location` -- `rotation` -- `transform(geom_object)` -- `get_forward_vector()` -- `__eq__(other)` -- `__ne__(other)` - -## `carla.BoundingBox` - -- `location` -- `extent` -- `__eq__(other)` -- `__ne__(other)` - -## `carla.Timestamp` - -- `frame` -- `frame_count` _deprecated, use `frame` instead_ -- `elapsed_seconds` -- `delta_seconds` -- `platform_timestamp` -- `__eq__(other)` -- `__ne__(other)` - -## `carla.Color` - -- `r` -- `g` -- `b` -- `a` -- `__eq__(other)` -- `__ne__(other)` - -## `carla.ColorConverter` - -- `Raw` -- `Depth` -- `LogarithmicDepth` -- `CityScapesPalette` - -## `carla.AttachmentType` - -- `Rigid` -- `SpringArm` - -## `carla.ActorAttributeType` - -- `Bool` -- `Int` -- `Float` -- `RGBColor` - -## `carla.TrafficLightState` - -- `Red` -- `Yellow` -- `Green` -- `Off` -- `Unknown` - -## `carla.LaneMarking` - -- `Other` -- `Broken` -- `Solid` - -# module `carla.command` - -`carla.command.FutureActor` (not yet spawned actor handler) - -## `carla.command.Response` - -- `actor_id` -- `error` -> str|empty -- `has_error()` - -## `carla.command.SpawnActor` - -- `__init__(blueprint, transform, parent=None)` -- `then(command)` - -## `carla.command.DestroyActor` - -- `__init__(actor)` -- `actor_id` - -## `carla.command.ApplyVehicleControl` - -- `__init__(actor, control)` -- `actor_id` -- `control` - -## `carla.command.ApplyWalkerControl` - -- `__init__(actor, control)` -- `actor_id` -- `control` - -## `carla.command.ApplyTransform` - -- `__init__(actor, transform)` -- `actor_id` -- `transform` - -## `carla.command.ApplyWalkerState` - -- `__init__(actor, transform, speed)` -- `actor_id` -- `transform` -- `speed` - -## `carla.command.ApplyVelocity` - -- `__init__(actor, velocity)` -- `actor_id` -- `velocity` - -## `carla.command.ApplyAngularVelocity` - -- `__init__(actor, angular_velocity)` -- `actor_id` -- `angular_velocity` - - -## `carla.command.ApplyImpulse` - -- `__init__(actor, impulse)` -- `actor_id` -- `impulse` - -## `carla.command.SetSimulatePhysics` - -- `__init__(actor, bool)` -- `actor_id` -- `enabled` - -## `carla.command.SetAutopilot` - -- `__init__(actor, bool)` -- `actor_id` -- `enabled` +### Overview +- [**carla**](#carla) _Module_ + - [**Map**](#carla.Map) _Class_ + - [**name**](#carla.Map.name) _Instance variable_ + - [**get_spawn_points**(**self**)](#carla.Map.get_spawn_points) _Method_ + - [**get_waypoint**(**self**)](#carla.Map.get_waypoint) _Method_ + - [**get_topology**(**self**)](#carla.Map.get_topology) _Method_ + - [**generate_waypoints**(**self**)](#carla.Map.generate_waypoints) _Method_ + - [**transform_to_geolocation**(**self**)](#carla.Map.transform_to_geolocation) _Method_ + - [**to_opendrive**(**self**)](#carla.Map.to_opendrive) _Method_ + - [**save_to_disk**(**self**, **path**)](#carla.Map.save_to_disk) _Method_ + - [**Client**](#carla.Client) _Class_ + - [**\__init__**(**self**, **host**, **port**, **worker_threads**=0)](#carla.Client.__init__) _Method_ + - [**set_timeout**(**self**, **seconds**)](#carla.Client.set_timeout) _Method_ + - [**get_client_version**(**self**)](#carla.Client.get_client_version) _Method_ + - [**get_server_version**(**self**)](#carla.Client.get_server_version) _Method_ + - [**get_world**(**self**)](#carla.Client.get_world) _Method_ + - [**get_available_maps**(**self**)](#carla.Client.get_available_maps) _Method_ + - [**reload_world**(**self**)](#carla.Client.reload_world) _Method_ + - [**load_world**(**self**, **map_name**)](#carla.Client.load_world) _Method_ + - [**start_recorder**(**self**, **filename**)](#carla.Client.start_recorder) _Method_ + - [**stop_recorder**(**self**)](#carla.Client.stop_recorder) _Method_ + - [**show_recorder_file_info**(**self**)](#carla.Client.show_recorder_file_info) _Method_ + - [**show_recorder_collisions**(**self**)](#carla.Client.show_recorder_collisions) _Method_ + - [**show_recorder_actors_blocked**(**self**)](#carla.Client.show_recorder_actors_blocked) _Method_ + - [**replay_file**(**self**)](#carla.Client.replay_file) _Method_ + - [**set_replayer_time_factor**(**self**)](#carla.Client.set_replayer_time_factor) _Method_ + - [**apply_batch**(**self**)](#carla.Client.apply_batch) _Method_ + - [**apply_batch_sync**(**self**)](#carla.Client.apply_batch_sync) _Method_ + +## Map _Class_ + +### Instance Variables +- **name** + Map name. + +### Methods +- **get_spawn_points**(**self**) +- **get_waypoint**(**self**) +- **get_topology**(**self**) +- **generate_waypoints**(**self**) +- **transform_to_geolocation**(**self**) +- **to_opendrive**(**self**) +- **save_to_disk**(**self**, **path**) + Save the OpenDrive of the current map to disk. + - **Parameters:** + - `path` – Path where will be saved. + +--- + +## Client _Class_ + +### Methods +- **\__init__**(**self**, **host**, **port**, **worker_threads**=0) + Client constructor. + - **Parameters:** + - `host` (_str_) – IP where Carla is running. + - `port` (_int_) – Port where Carla is running. + - `worker_threads` (_int_) – Number of working threads. +- **set_timeout**(**self**, **seconds**) + Sets the server timeout in seconds. + - **Parameters:** + - `seconds` (_float_) – New timeout value in seconds. +- **get_client_version**(**self**) + Get the client version as a string. +- **get_server_version**(**self**) + Get the server version as a string. +- **get_world**(**self**) + Get the server version as a string. +- **get_available_maps**(**self**) +- **reload_world**(**self**) + - **Raises:** RuntimeError +- **load_world**(**self**, **map_name**) + - **Parameters:** + - `map_name` (_str_) – Name of the map to load. +- **start_recorder**(**self**, **filename**) + - **Parameters:** + - `filename` (_str_) – Name of the recorder file to load. +- **stop_recorder**(**self**) +- **show_recorder_file_info**(**self**) +- **show_recorder_collisions**(**self**) +- **show_recorder_actors_blocked**(**self**) +- **replay_file**(**self**) +- **set_replayer_time_factor**(**self**) +- **apply_batch**(**self**) +- **apply_batch_sync**(**self**) + +--- diff --git a/PythonAPI/docs/client.yml b/PythonAPI/docs/client.yml index d1343f044..600a5216a 100644 --- a/PythonAPI/docs/client.yml +++ b/PythonAPI/docs/client.yml @@ -1,5 +1,5 @@ --- -- module_name: client +- module_name: carla doc: > # - CLASSES ------------------------------ @@ -70,6 +70,7 @@ - def_name: reload_world params: - param_name: self + raises: RuntimeError doc: > # -------------------------------------- - def_name: load_world diff --git a/PythonAPI/docs/doc_gen.py b/PythonAPI/docs/doc_gen.py index 81750bb3b..44582b5a3 100755 --- a/PythonAPI/docs/doc_gen.py +++ b/PythonAPI/docs/doc_gen.py @@ -1,4 +1,5 @@ #!/usr/bin/env python +# -*- coding: utf-8 -*- # Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma de # Barcelona (UAB). @@ -9,6 +10,9 @@ import os import yaml +def join(elem, separator = ''): + return separator.join(elem) + class MarkdownFile: def __init__(self): self._data = "" @@ -16,113 +20,300 @@ class MarkdownFile: self.endl = ' \n' def data(self): - return str(self._data) + return self._data - def push_list(self): + def list_push(self, buf=''): + if buf: + self.text(join([ + ' ' * self._list_depth if self._list_depth != 0 else '', '- ', buf])) self._list_depth = (self._list_depth + 1) - def pop_list(self): + def list_pushn(self, buf): + self.list_push(join([buf, self.endl])) + + def list_pop(self): self._list_depth = max(self._list_depth - 1, 0) + def list_popn(self): + self.list_pop() + self._data = ''.join([self._data, '\n']) + def list_depth(self): if self._list_depth == 0: return '' - return ''.join([' ' * (self._list_depth + 1)]) + return ''.join([' ' * self._list_depth]) def list_item(self, buf): - self._data = ''.join([self._data, self.list_depth()[:-2], '* ', buf]) + self._data = ''.join([self._data, self.list_depth()[:-2], '- ', buf]) def numeric_list_item(self, buf): self._data = ''.join([self._data, self.list_depth(), '1. ', buf]) + def separator(self): + self._data = ''.join([self._data, '\n---\n']) + + def new_line(self): + self._data = ''.join([self._data, self.endl]) + def text(self, buf): - self._data = ''.join([self._data, self.list_depth(), buf]) + self._data = ''.join([self._data, buf]) + + def textn(self, buf): + self._data = ''.join([self._data, self.list_depth(), buf, self.endl]) def title(self, strongness, buf): self._data = ''.join([ self._data, '\n', self.list_depth(), '#' * strongness, ' ', buf, '\n']) - @classmethod - def italic(cls, buf): - return ''.join(['_', buf, '_']) - - @classmethod - def bold(cls, buf): - return ''.join(['**', buf, '**']) - - @classmethod - def code(cls, buf): - return ''.join(['`', buf, '`']) - def code_block(self, buf, language=''): return ''.join(['```', language, '\n', self.list_depth(), buf, '\n', self.list_depth(), '```\n']) -class YamlIO: - """YAML loader and writer""" +def italic(buf): + return ''.join(['_', buf, '_']) - def __init__(self, file_path): - """Constructor that loads the yaml file""" - with open(file_path) as yaml_file: +def bold(buf): + return ''.join(['**', buf, '**']) + +def code(buf): + return ''.join(['`', buf, '`']) + +def brackets(buf): + return ''.join(['[', buf, ']']) + +def parentheses(buf): + return ''.join(['(', buf, ')']) + +def small(buf): + return ''.join(['', buf, '']) + +def sub(buf): + return ''.join(['', buf, '']) + +def html_key(buf): + return ''.join(['']) + +def color(col, buf): + return ''.join(['', buf, '']) + +def valid_dic_val(dic, value): + return value in dic and dic[value] + +class YamlFile: + """Yaml file class""" + def __init__(self, path): + self._path = path + with open(path) as yaml_file: self.data = yaml.safe_load(yaml_file) + def get_modules(self): + return [module for module in self.data] + + +def prettify_doc(doc): + doc = doc.strip() + doc += '' if doc[-1:] == '.' else '.' + return doc + +def gen_stub_method_def(method): + """Return python def as it should be written in stub files""" + param = '' + method_name = method['def_name'] + for p in method['params']: + p_type = ''.join([': ', str(p['type'])]) if 'type' in p else '' + default = ''.join([' = ', str(p['default'])]) if 'default' in p else '' + param = ''.join([param, p['param_name'], p_type, default, ', ']) + param = param[:-2] # delete the last ', ' + return_type = ''.join([' -> ', method['return']]) if 'return' in method else '' + return ''.join([method_name, parentheses(param), return_type]) + + +def gen_doc_method_def(method, indx=False): + """Return python def as it should be written in docs""" + param = '' + method_name = method['def_name'] + # to correclty render methods like __init__ in md + if method_name[0] == '_': + method_name = '\\' + method_name + if indx: + method_name = bold(method_name) + else: + method_name = bold(color('#64BA2E', method_name)) + for p in method['params']: + default = ''.join(['=', str(p['default'])]) if 'default' in p else '' + if indx: + param = ''.join([param, bold(p['param_name']), default, ', ']) + else: + param = ''.join([param, '', bold(p['param_name']), default, '', ', ']) + param = param[:-2] # delete the last ', ' + return ''.join([method_name, parentheses(param)]) + + +def gen_inst_var_indx(inst_var, class_key): + inst_var_name = inst_var['var_name'] + inst_var_key = '.'.join([class_key, inst_var_name]) + return ''.join([ + brackets(bold(inst_var_name)), + parentheses(inst_var_key), ' ', + sub(italic('Instance variable'))]) + + +def gen_method_indx(method, class_key): + method_name = method['def_name'] + method_key = '.'.join([class_key, method_name]) + method_def = gen_doc_method_def(method, True) + return ''.join([ + brackets(method_def), + parentheses(method_key), ' ', + sub(italic('Method'))]) + + +def add_doc_method_param(md, param): + param_name = param['param_name'] + param_type = '' + param_doc = '' + if valid_dic_val(param, 'type'): + param_type = param['type'] + if valid_dic_val(param, 'doc'): + param_doc = prettify_doc(param['doc']) + param_type = '' if not param_type else parentheses(italic(param_type)) + md.list_push(code(param_name) + ' ' + param_type + ' – ') + if param_doc: + md.textn(param_doc) + md.list_pop() + + +def add_doc_method(md, method, class_key): + method_name = method['def_name'] + method_key = '.'.join([class_key, method_name]) + method_def = gen_doc_method_def(method) + md.list_pushn(''.join([html_key(method_key), method_def])) + # method doc + if 'doc' in method and method['doc'] is not '': + md.textn(prettify_doc(method['doc'])) + # ignore if only have the parameter self + if valid_dic_val(method, 'params') and \ + len(method['params']) != 1 and \ + method['params'][0] != 'self': + md.list_push(bold('Parameters:') + '\n') + for param in method['params']: + if param['param_name'] == 'self': + continue + add_doc_method_param(md, param) + md.list_pop() + # raises error doc + if valid_dic_val(method, 'raises'): + md.list_pushn(bold('Raises:') + ' ' + method['raises']) + md.list_pop() + md.list_pop() + + +def add_doc_inst_var(md, inst_var, class_key): + var_name = inst_var['var_name'] + var_key = '.'.join([class_key, var_name]) + md.list_pushn(html_key(var_key) + bold(var_name)) + md.textn(prettify_doc(inst_var['doc'])) + md.list_pop() + +def dump_keys(d, lvl=0): + for k, v in d.iteritems(): + print '%s%s' % (lvl * ' ', k) + if type(v) == dict: + dump_keys(v, lvl+1) + + +class Documentation: + """Main documentation class""" + + def __init__(self, path): + self._path = path + self._files = [f for f in os.listdir(path) if f.endswith('.yml')] + self._yamls = list() + for yaml_file in self._files: + self._yamls.append(YamlFile(os.path.join(path, yaml_file))) + # merge modules + self.master_dict = dict() + for yaml_file in self._yamls: + for module in yaml_file.get_modules(): + module_name = module['module_name'] + if module_name not in self.master_dict: + self.master_dict[module_name] = module + else: + for new_module in module['classes']: + self.master_dict[module_name]['classes'].append(new_module) + + def gen_overview(self): + """Generates a referenced index for markdown file""" + md = MarkdownFile() + md.title(3, 'Overview') + for module_name in self.master_dict: + module = self.master_dict[module_name] + module_key = '#' + module_name + md.list_pushn( + brackets(bold(module_key[1:])) + + parentheses(module_key) + ' ' + + sub(italic('Module'))) + # Generate class overview (if any) + if 'classes' in module and module['classes']: + for cl in module['classes']: + class_name = cl['class_name'] + class_key = '.'.join([module_key, class_name]) + md.list_pushn( + brackets(bold(class_name)) + + parentheses(class_key) + ' ' + + sub(italic('Class'))) + # Generate class instance variables overview (if any) + if 'instance_variables' in cl and cl['instance_variables']: + for inst_var in cl['instance_variables']: + md.list_push(gen_inst_var_indx(inst_var, class_key)) + md.list_popn() + # Generate class methods overview (if any) + if 'methods' in cl and cl['methods']: + for method in cl['methods']: + md.list_push(gen_method_indx(method, class_key)) + md.list_popn() + md.list_pop() + md.list_pop() + return md.data() + + def gen_body(self): + """Generates the documentaion body""" + md = MarkdownFile() + for module_name in self.master_dict: + module = self.master_dict[module_name] + module_key = module_name + # Generate class doc (if any) + if valid_dic_val(module, 'classes'): + for cl in module['classes']: + class_name = cl['class_name'] + class_key = '.'.join([module_key, class_name]) + md.title(2, + html_key(class_key) + + class_name + ' ' + + small(italic('Class'))) + # Generate instance variable doc (if any) + if valid_dic_val(cl, 'instance_variables'): + md.title(3, 'Instance Variables') + for inst_var in cl['instance_variables']: + add_doc_inst_var(md, inst_var, class_key) + # Generate method doc (if any) + if valid_dic_val(cl, 'methods'): + md.title(3, 'Methods') + for method in cl['methods']: + add_doc_method(md, method, class_key) + md.separator() + return md.data().strip() + def gen_markdown(self): - """Generates the markdown file""" - md_data = '' - for module in self.data: - # print('Generating module: ' + module['module_name']) - md = MarkdownFile() - if module['classes']: - for c in module['classes']: - class_name = c['class_name'] - doc = c['doc'] - variables = c['instance_variables'] - methods = c['methods'] - - md.title(2, ''.join([md.italic('class'), ' ', md.code('carla.' + class_name)])) - md.text(doc) - - if variables: - md.title(4, 'Instance Variables') - md.push_list() - for var in variables: - md.list_item(''.join([md.code(var['var_name']), md.endl])) - md.text(var['doc']) - md.pop_list() - - if methods: - md.title(4, 'Methods') - md.push_list() - for m in methods: - param = '' - for p in m['params']: - p_type = ''.join([': ', str(p['type'])]) if 'type' in p else '' - default = ''.join([' = ', str(p['default'])]) if 'default' in p else '' - param = ''.join([param, p['param_name'], p_type, default, ', ']) - param = param[:-2] # delete the last ', ' - return_type = ''.join([' -> ', m['return']]) if 'return' in m else '' - md.list_item(''.join([md.code(''.join([m['def_name'], '(', param, ')', return_type])), md.endl])) - if 'doc' in m and m['doc'] is not '': - doc = m['doc'].strip() - md.text(''.join([doc, md.endl])) - md.pop_list() - md_data = ''.join([md_data, md.data().strip()]) - return md_data - + """Generates the whole markdown file""" + return '\n'.join([self.gen_overview(), self.gen_body()]).strip() def main(): """Main function""" script_path = os.path.dirname(os.path.abspath(__file__)) - yml_files = [f for f in os.listdir(script_path) if f.endswith('.yml')] - - data = '' - - for yml_file in yml_files: - yml = YamlIO(os.path.join(script_path, yml_file)) - data = '\n\n'.join([data, yml.gen_markdown()]) - data = data.strip() - with open(os.path.join(script_path, 'Output.md'), 'w') as md_file: - md_file.write(data) + docs = Documentation(script_path) + with open(os.path.join(script_path, '../../Docs/python_api.md'), 'w') as md_file: + md_file.write(docs.gen_markdown()) if __name__ == "__main__": main() diff --git a/PythonAPI/docs/map.yml b/PythonAPI/docs/map.yml index 8f14c0236..5eba2041a 100644 --- a/PythonAPI/docs/map.yml +++ b/PythonAPI/docs/map.yml @@ -1,5 +1,5 @@ --- -- module_name: map +- module_name: carla doc: > # - CLASSES ------------------------------ diff --git a/PythonAPI/docs/requirements.txt b/PythonAPI/docs/requirements.txt new file mode 100644 index 000000000..c3726e8bf --- /dev/null +++ b/PythonAPI/docs/requirements.txt @@ -0,0 +1 @@ +pyyaml