Merge branch 'master' of github.com:matrix-org/matrix-doc
This commit is contained in:
commit
232b10b0f6
11 changed files with 272 additions and 38 deletions
|
@ -1,4 +1,5 @@
|
||||||
{
|
{
|
||||||
|
"title": "PushRule",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"default": {
|
"default": {
|
||||||
|
@ -17,4 +18,4 @@
|
||||||
"type": "array"
|
"type": "array"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,60 +1,65 @@
|
||||||
{
|
{
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"content": {
|
"content": {
|
||||||
"items": {
|
"items": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
|
"title": "PushRule",
|
||||||
"allOf": [
|
"allOf": [
|
||||||
{
|
{
|
||||||
"$ref": "push_rule.json"
|
"$ref": "push_rule.json"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"type": "array"
|
"type": "array"
|
||||||
},
|
},
|
||||||
"override": {
|
"override": {
|
||||||
"items": {
|
"items": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
|
"title": "PushRule",
|
||||||
"allOf": [
|
"allOf": [
|
||||||
{
|
{
|
||||||
"$ref": "push_rule.json"
|
"$ref": "push_rule.json"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"type": "array"
|
"type": "array"
|
||||||
},
|
},
|
||||||
"sender": {
|
"sender": {
|
||||||
"items": {
|
"items": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
|
"title": "PushRule",
|
||||||
"allOf": [
|
"allOf": [
|
||||||
{
|
{
|
||||||
"$ref": "push_rule.json"
|
"$ref": "push_rule.json"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"type": "array"
|
"type": "array"
|
||||||
},
|
},
|
||||||
"underride": {
|
"underride": {
|
||||||
"items": {
|
"items": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
|
"title": "PushRule",
|
||||||
"allOf": [
|
"allOf": [
|
||||||
{
|
{
|
||||||
"$ref": "push_rule.json"
|
"$ref": "push_rule.json"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"type": "array"
|
"type": "array"
|
||||||
},
|
},
|
||||||
"room": {
|
"room": {
|
||||||
"items": {
|
"items": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
|
"title": "PushRule",
|
||||||
"allOf": [
|
"allOf": [
|
||||||
{
|
{
|
||||||
"$ref": "push_rule.json"
|
"$ref": "push_rule.json"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"type": "array"
|
"type": "array"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"description": "List of events",
|
"description": "List of events",
|
||||||
"items": {
|
"items": {
|
||||||
|
"title": "Event",
|
||||||
"type": "object"
|
"type": "object"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -241,6 +241,9 @@ paths:
|
||||||
"type": "m.room.member",
|
"type": "m.room.member",
|
||||||
"state_key": "@bob:example.com",
|
"state_key": "@bob:example.com",
|
||||||
"content": {"membership": "join"},
|
"content": {"membership": "join"},
|
||||||
|
"unsigned": {
|
||||||
|
"prev_content": {"membership": "invite"}
|
||||||
|
},
|
||||||
"origin_server_ts": 1417731086795
|
"origin_server_ts": 1417731086795
|
||||||
},
|
},
|
||||||
"$74686972643033:example.com": {
|
"$74686972643033:example.com": {
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
"properties": {
|
"properties": {
|
||||||
"content": {
|
"content": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
|
"title": "EventContent",
|
||||||
"description": "The fields in this object will vary depending on the type of event. When interacting with the REST API, this is the HTTP body."
|
"description": "The fields in this object will vary depending on the type of event. When interacting with the REST API, this is the HTTP body."
|
||||||
},
|
},
|
||||||
"type": {
|
"type": {
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
"description": "A unique key which defines the overwriting semantics for this piece of room state. This value is often a zero-length string. The presence of this key makes this event a State Event. The key MUST NOT start with '_'."
|
"description": "A unique key which defines the overwriting semantics for this piece of room state. This value is often a zero-length string. The presence of this key makes this event a State Event. The key MUST NOT start with '_'."
|
||||||
},
|
},
|
||||||
"prev_content": {
|
"prev_content": {
|
||||||
|
"title": "EventContent",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"description": "Optional. The previous ``content`` for this event. If there is no previous content, this key will be missing."
|
"description": "Optional. The previous ``content`` for this event. If there is no previous content, this key will be missing."
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
"properties": {
|
"properties": {
|
||||||
"content": {
|
"content": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
|
"title": "EventContent",
|
||||||
"properties": {
|
"properties": {
|
||||||
"membership": {
|
"membership": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
|
|
|
@ -12,6 +12,42 @@ server-server and application-service APIs, and are described below.
|
||||||
{{common_state_event_fields}}
|
{{common_state_event_fields}}
|
||||||
|
|
||||||
|
|
||||||
|
Differences between /v1 and /v2 events
|
||||||
|
--------------------------------------
|
||||||
|
|
||||||
|
There are a few differences between how events are formatted for sending
|
||||||
|
between servers over federation and how they are formatted for sending between
|
||||||
|
a server and its clients.
|
||||||
|
|
||||||
|
Additionally there are a few differences between the format of events in the
|
||||||
|
responses to client APIs with a /v1 prefix and responses APIs with a /v2
|
||||||
|
prefix.
|
||||||
|
|
||||||
|
Events in responses for APIs with the /v2 prefix are generated from an event
|
||||||
|
formatted for federation by:
|
||||||
|
|
||||||
|
* Removing the following keys:
|
||||||
|
``auth_events``, ``prev_events``, ``hashes``, ``signatures``, ``depth``,
|
||||||
|
``origin``, ``prev_state``.
|
||||||
|
* Adding an ``age`` to the ``unsigned`` object which gives the time in
|
||||||
|
milliseconds that has ellapsed since the event was sent.
|
||||||
|
* Adding a ``prev_content`` to the ``unsigned`` object if the event is
|
||||||
|
a ``state event`` which gives previous content of that state key.
|
||||||
|
* Adding a ``redacted_because`` to the ``unsigned`` object if the event was
|
||||||
|
redacted which gives the event that redacted it.
|
||||||
|
* Adding a ``transaction_id`` if the event was sent by the client requesting it.
|
||||||
|
|
||||||
|
Events in responses for APIs with the /v1 prefix are generated from an event
|
||||||
|
formatted for the /v2 prefix by:
|
||||||
|
|
||||||
|
* Moving the folling keys from the ``unsigned`` object to the top level event
|
||||||
|
object: ``age``, ``redacted_because``, ``replaces_state``, ``prev_content``.
|
||||||
|
* Removing the ``unsigned`` object.
|
||||||
|
* Rename the ``sender`` key to ``user_id``.
|
||||||
|
* If the event was an ``m.room.member`` with ``membership`` set to ``invite``
|
||||||
|
then adding a ``invite_room_state`` key to the top level event object.
|
||||||
|
|
||||||
|
|
||||||
Size limits
|
Size limits
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
|
|
|
@ -116,12 +116,63 @@ of the client-server API will resolve this by attaching the transaction ID of th
|
||||||
sending request to the event itself.
|
sending request to the event itself.
|
||||||
|
|
||||||
|
|
||||||
|
Calculating the display name for a user
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Clients may wish to show the human-readable display name of a room member as
|
||||||
|
part of a membership list, or when they send a message. However, different
|
||||||
|
members may have conflicting display names. Display names MUST be disambiguated
|
||||||
|
before showing them to the user, in order to prevent spoofing of other users.
|
||||||
|
|
||||||
|
To ensure this is done consistently across clients, clients SHOULD use the
|
||||||
|
following algorithm to calculate a disambiguated display name for a given user:
|
||||||
|
|
||||||
|
1. Inspect the ``m.room.member`` state event for the relevant user id.
|
||||||
|
2. If the ``m.room.member`` state event has no ``displayname`` field, or if
|
||||||
|
that field has a ``null`` value, use the raw user id as the display
|
||||||
|
name. Otherwise:
|
||||||
|
3. If the ``m.room.member`` event has a ``displayname`` which is unique among
|
||||||
|
members of the room with ``membership: join`` or ``membership: invite``, use
|
||||||
|
the given ``displayname`` as the user-visible display name. Otherwise:
|
||||||
|
4. The ``m.room.member`` event has a non-unique ``displayname``. This should be
|
||||||
|
disambiguated using the user id, for example "display name
|
||||||
|
(@id:homeserver.org)".
|
||||||
|
|
||||||
|
.. TODO-spec
|
||||||
|
what does it mean for a ``displayname`` to be 'unique'? Are we
|
||||||
|
case-sensitive? Do we care about homograph attacks? See
|
||||||
|
https://matrix.org/jira/browse/SPEC-221.
|
||||||
|
|
||||||
|
Developers should take note of the following when implementing the above
|
||||||
|
algorithm:
|
||||||
|
|
||||||
|
* The user-visible display name of one member can be affected by changes in the
|
||||||
|
state of another member. For example, if ``@user1:matrix.org`` is present in
|
||||||
|
a room, with ``displayname: Alice``, then when ``@user2:example.com`` joins
|
||||||
|
the room, also with ``displayname: Alice``, *both* users must be given
|
||||||
|
disambiguated display names. Similarly, when one of the users then changes
|
||||||
|
their display name, there is no longer a clash, and *both* users can be given
|
||||||
|
their chosen display name. Clients should be alert to this possibility and
|
||||||
|
ensure that all affected users are correctly renamed.
|
||||||
|
|
||||||
|
* The display name of a room may also be affected by changes in the membership
|
||||||
|
list. This is due to the room name sometimes being based on user display
|
||||||
|
names (see `Calculating the display name for a room`_).
|
||||||
|
|
||||||
|
* If the entire membership list is searched for clashing display names, this
|
||||||
|
leads to an O(N^2) implementation for building the list of room members. This
|
||||||
|
will be very inefficient for rooms with large numbers of members. It is
|
||||||
|
recommended that client implementations maintain a hash table mapping from
|
||||||
|
``displayname`` to a list of room members using that name. Such a table can
|
||||||
|
then be used for efficient calculation of whether disambiguation is needed.
|
||||||
|
|
||||||
|
|
||||||
Displaying membership information with messages
|
Displaying membership information with messages
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
Clients may wish to show the display name and avatar URL of the room member who
|
Clients may wish to show the display name and avatar URL of the room member who
|
||||||
sent a message. This can be achieved by inspecting the ``m.room.member`` state
|
sent a message. This can be achieved by inspecting the ``m.room.member`` state
|
||||||
event for that user ID.
|
event for that user ID (see `Calculating the display name for a user`_).
|
||||||
|
|
||||||
When a user paginates the message history, clients may wish to show the
|
When a user paginates the message history, clients may wish to show the
|
||||||
**historical** display name and avatar URL for a room member. This is possible
|
**historical** display name and avatar URL for a room member. This is possible
|
||||||
|
@ -133,6 +184,85 @@ events update the old state. When paginated events are processed sequentially,
|
||||||
the old state represents the state of the room *at the time the event was sent*.
|
the old state represents the state of the room *at the time the event was sent*.
|
||||||
This can then be used to set the historical display name and avatar URL.
|
This can then be used to set the historical display name and avatar URL.
|
||||||
|
|
||||||
|
|
||||||
|
Calculating the display name for a room
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Clients may wish to show a human-readable name for a room. There are a number
|
||||||
|
of possibilities for choosing a useful name. To ensure that rooms are named
|
||||||
|
consistently across clients, clients SHOULD use the following algorithm to
|
||||||
|
choose a name:
|
||||||
|
|
||||||
|
1. If the room has an `m.room.name`_ state event, use the name given by that
|
||||||
|
event.
|
||||||
|
|
||||||
|
#. If the room has an `m.room.canonical_alias`_ state event, use the alias
|
||||||
|
given by that event.
|
||||||
|
|
||||||
|
#. If neither of the above events are present, a name should be composed based
|
||||||
|
on the members of the room. Clients should consider `m.room.member`_ events
|
||||||
|
for users other than the logged-in user, with ``membership: join`` or
|
||||||
|
``membership: invite``.
|
||||||
|
|
||||||
|
.. _active_members:
|
||||||
|
|
||||||
|
i. If there is only one such event, the display name for the room should be
|
||||||
|
the `disambiguated display name`_ of the corresponding user.
|
||||||
|
|
||||||
|
#. If there are two such events, they should be lexicographically sorted by
|
||||||
|
their ``state_key`` (i.e. the corresponding user IDs), and the display
|
||||||
|
name for the room should be the `disambiguated display name`_ of both
|
||||||
|
users: "<user1> and <user2>", or a localised variant thereof.
|
||||||
|
|
||||||
|
#. If there are three or more such events, the display name for the room
|
||||||
|
should be based on the disambiguated display name of the user
|
||||||
|
corresponding to the first such event, under a lexicographical sorting
|
||||||
|
according to their ``state_key``. The display name should be in the
|
||||||
|
format "<user1> and <N> others" (or a localised variant thereof), where N
|
||||||
|
is the number of `m.room.member`_ events with ``membership: join`` or
|
||||||
|
``membership: invite``, excluding the logged-in user and "user1".
|
||||||
|
|
||||||
|
For example, if Alice joins a room, where Bob (whose user id is
|
||||||
|
``@superuser:example.com``), Carol (user id ``@carol:example.com``) and
|
||||||
|
Dan (user id ``@dan:matrix.org``) are in conversation, Alice's
|
||||||
|
client should show the room name as "Carol and 2 others".
|
||||||
|
|
||||||
|
.. TODO-spec
|
||||||
|
Sorting by user_id certainly isn't ideal, as IDs at the start of the
|
||||||
|
alphabet will end up dominating room names: they will all be called
|
||||||
|
"Arathorn and 15 others". Furthermore - user_ids are not necessarily
|
||||||
|
ASCII, which means we need to either specify a collation order, or specify
|
||||||
|
how to choose one.
|
||||||
|
|
||||||
|
Ideally we might sort by the time when the user was first invited to, or
|
||||||
|
first joined the room. But we don't have this information.
|
||||||
|
|
||||||
|
See https://matrix.org/jira/browse/SPEC-267 for further discussion.
|
||||||
|
|
||||||
|
#. If the room has no ``m.room.name`` or ``m.room.canonical_alias`` events, and
|
||||||
|
no active members other than the current user, clients should consider
|
||||||
|
``m.room.member`` events with ``membership: leave``. If such events exist, a
|
||||||
|
display name such as "Empty room (was <user1> and <N> others)" (or a
|
||||||
|
localised variant thereof) should be used, following similar rules as for
|
||||||
|
active members (see `above <active_members_>`_).
|
||||||
|
|
||||||
|
#. A complete absence of ``m.room.name``, ``m.room.canonical_alias``, and
|
||||||
|
``m.room.member`` events is likely to indicate a problem with creating the
|
||||||
|
room or synchronising the state table; however clients should still handle
|
||||||
|
this situation. A display name such as "Empty room" (or a localised variant
|
||||||
|
thereof) should be used in this situation.
|
||||||
|
|
||||||
|
.. _`disambiguated display name`: `Calculating the display name for a user`_
|
||||||
|
|
||||||
|
Clients SHOULD NOT use `m.room.aliases`_ events as a source for room names, as
|
||||||
|
it is difficult for clients to agree on the best alias to use, and aliases can
|
||||||
|
change unexpectedly.
|
||||||
|
|
||||||
|
.. TODO-spec
|
||||||
|
How can we make this less painful for clients to implement, without forcing
|
||||||
|
an English-language implementation on them all?
|
||||||
|
|
||||||
|
|
||||||
Server behaviour
|
Server behaviour
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,8 @@
|
||||||
================== ================= ===========================================
|
================== ================= ===========================================
|
||||||
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
Example::
|
Example:
|
||||||
|
|
||||||
|
.. code:: json
|
||||||
|
|
||||||
{{example | jsonify(4, 4)}}
|
{{example | jsonify(4, 4)}}
|
||||||
|
|
|
@ -28,7 +28,25 @@ ROOM_EVENT = "core-event-schema/room_event.json"
|
||||||
STATE_EVENT = "core-event-schema/state_event.json"
|
STATE_EVENT = "core-event-schema/state_event.json"
|
||||||
|
|
||||||
|
|
||||||
def get_json_schema_object_fields(obj, enforce_title=False):
|
def resolve_references(path, schema):
|
||||||
|
if isinstance(schema, dict):
|
||||||
|
result = {}
|
||||||
|
for key, value in schema.items():
|
||||||
|
if key == "$ref":
|
||||||
|
path = os.path.join(os.path.dirname(path), value)
|
||||||
|
with open(path) as f:
|
||||||
|
schema = json.load(f)
|
||||||
|
return resolve_references(path, schema)
|
||||||
|
else:
|
||||||
|
result[key] = resolve_references(path, value)
|
||||||
|
return result
|
||||||
|
elif isinstance(schema, list):
|
||||||
|
return [resolve_references(path, value) for value in schema]
|
||||||
|
else:
|
||||||
|
return schema
|
||||||
|
|
||||||
|
|
||||||
|
def get_json_schema_object_fields(obj, enforce_title=False, include_parents=False):
|
||||||
# Algorithm:
|
# Algorithm:
|
||||||
# f.e. property => add field info (if field is object then recurse)
|
# f.e. property => add field info (if field is object then recurse)
|
||||||
if obj.get("type") != "object":
|
if obj.get("type") != "object":
|
||||||
|
@ -36,9 +54,9 @@ def get_json_schema_object_fields(obj, enforce_title=False):
|
||||||
"get_json_schema_object_fields: Object %s isn't an object." % obj
|
"get_json_schema_object_fields: Object %s isn't an object." % obj
|
||||||
)
|
)
|
||||||
if enforce_title and not obj.get("title"):
|
if enforce_title and not obj.get("title"):
|
||||||
raise Exception(
|
# Force a default titile of "NO_TITLE" to make it obvious in the
|
||||||
"get_json_schema_object_fields: Nested object %s doesn't have a title." % obj
|
# specification output which parts of the schema are missing a title
|
||||||
)
|
obj["title"] = 'NO_TITLE'
|
||||||
|
|
||||||
required_keys = obj.get("required")
|
required_keys = obj.get("required")
|
||||||
if not required_keys:
|
if not required_keys:
|
||||||
|
@ -73,9 +91,15 @@ def get_json_schema_object_fields(obj, enforce_title=False):
|
||||||
"Object %s has no properties or parents." % obj
|
"Object %s has no properties or parents." % obj
|
||||||
)
|
)
|
||||||
if not props: # parents only
|
if not props: # parents only
|
||||||
|
if include_parents:
|
||||||
|
if obj["title"] == "NO_TITLE" and parents[0].get("title"):
|
||||||
|
obj["title"] = parents[0].get("title")
|
||||||
|
props = parents[0].get("properties")
|
||||||
|
|
||||||
|
if not props:
|
||||||
return [{
|
return [{
|
||||||
"title": obj["title"],
|
"title": obj["title"],
|
||||||
"parent": parents[0]["$ref"],
|
"parent": parents[0].get("$ref"),
|
||||||
"no-table": True
|
"no-table": True
|
||||||
}]
|
}]
|
||||||
|
|
||||||
|
@ -91,7 +115,8 @@ def get_json_schema_object_fields(obj, enforce_title=False):
|
||||||
if prop_val == "object":
|
if prop_val == "object":
|
||||||
nested_object = get_json_schema_object_fields(
|
nested_object = get_json_schema_object_fields(
|
||||||
props[key_name]["additionalProperties"],
|
props[key_name]["additionalProperties"],
|
||||||
enforce_title=True
|
enforce_title=True,
|
||||||
|
include_parents=include_parents,
|
||||||
)
|
)
|
||||||
key = props[key_name]["additionalProperties"].get(
|
key = props[key_name]["additionalProperties"].get(
|
||||||
"x-pattern", "string"
|
"x-pattern", "string"
|
||||||
|
@ -103,8 +128,9 @@ def get_json_schema_object_fields(obj, enforce_title=False):
|
||||||
value_type = "{string: %s}" % prop_val
|
value_type = "{string: %s}" % prop_val
|
||||||
else:
|
else:
|
||||||
nested_object = get_json_schema_object_fields(
|
nested_object = get_json_schema_object_fields(
|
||||||
props[key_name],
|
props[key_name],
|
||||||
enforce_title=True
|
enforce_title=True,
|
||||||
|
include_parents=include_parents,
|
||||||
)
|
)
|
||||||
value_type = "{%s}" % nested_object[0]["title"]
|
value_type = "{%s}" % nested_object[0]["title"]
|
||||||
|
|
||||||
|
@ -114,13 +140,17 @@ def get_json_schema_object_fields(obj, enforce_title=False):
|
||||||
# if the items of the array are objects then recurse
|
# if the items of the array are objects then recurse
|
||||||
if props[key_name]["items"]["type"] == "object":
|
if props[key_name]["items"]["type"] == "object":
|
||||||
nested_object = get_json_schema_object_fields(
|
nested_object = get_json_schema_object_fields(
|
||||||
props[key_name]["items"],
|
props[key_name]["items"],
|
||||||
enforce_title=True
|
enforce_title=True,
|
||||||
|
include_parents=include_parents,
|
||||||
)
|
)
|
||||||
value_type = "[%s]" % nested_object[0]["title"]
|
value_type = "[%s]" % nested_object[0]["title"]
|
||||||
tables += nested_object
|
tables += nested_object
|
||||||
else:
|
else:
|
||||||
value_type = "[%s]" % props[key_name]["items"]["type"]
|
value_type = props[key_name]["items"]["type"]
|
||||||
|
if isinstance(value_type, list):
|
||||||
|
value_type = " or ".join(value_type)
|
||||||
|
value_type = "[%s]" % value_type
|
||||||
array_enums = props[key_name]["items"].get("enum")
|
array_enums = props[key_name]["items"].get("enum")
|
||||||
if array_enums:
|
if array_enums:
|
||||||
if len(array_enums) > 1:
|
if len(array_enums) > 1:
|
||||||
|
@ -137,12 +167,16 @@ def get_json_schema_object_fields(obj, enforce_title=False):
|
||||||
if props[key_name].get("enum"):
|
if props[key_name].get("enum"):
|
||||||
if len(props[key_name].get("enum")) > 1:
|
if len(props[key_name].get("enum")) > 1:
|
||||||
value_type = "enum"
|
value_type = "enum"
|
||||||
|
if desc:
|
||||||
|
desc += " "
|
||||||
desc += (
|
desc += (
|
||||||
" One of: %s" % json.dumps(props[key_name]["enum"])
|
"One of: %s" % json.dumps(props[key_name]["enum"])
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
|
if desc:
|
||||||
|
desc += " "
|
||||||
desc += (
|
desc += (
|
||||||
" Must be '%s'." % props[key_name]["enum"][0]
|
"Must be '%s'." % props[key_name]["enum"][0]
|
||||||
)
|
)
|
||||||
if isinstance(value_type, list):
|
if isinstance(value_type, list):
|
||||||
value_type = " or ".join(value_type)
|
value_type = " or ".join(value_type)
|
||||||
|
@ -154,12 +188,22 @@ def get_json_schema_object_fields(obj, enforce_title=False):
|
||||||
"desc": desc,
|
"desc": desc,
|
||||||
"req_str": "**Required.** " if required else ""
|
"req_str": "**Required.** " if required else ""
|
||||||
})
|
})
|
||||||
return tables
|
|
||||||
|
titles = set()
|
||||||
|
filtered = []
|
||||||
|
for table in tables:
|
||||||
|
if table.get("title") in titles:
|
||||||
|
continue
|
||||||
|
|
||||||
|
titles.add(table.get("title"))
|
||||||
|
filtered.append(table)
|
||||||
|
|
||||||
|
return filtered
|
||||||
|
|
||||||
|
|
||||||
class MatrixUnits(Units):
|
class MatrixUnits(Units):
|
||||||
|
|
||||||
def _load_swagger_meta(self, api, group_name):
|
def _load_swagger_meta(self, filepath, api, group_name):
|
||||||
endpoints = []
|
endpoints = []
|
||||||
for path in api["paths"]:
|
for path in api["paths"]:
|
||||||
for method in api["paths"][path]:
|
for method in api["paths"][path]:
|
||||||
|
@ -262,7 +306,10 @@ class MatrixUnits(Units):
|
||||||
if is_array_of_objects:
|
if is_array_of_objects:
|
||||||
req_obj = req_obj["items"]
|
req_obj = req_obj["items"]
|
||||||
|
|
||||||
req_tables = get_json_schema_object_fields(req_obj)
|
req_tables = get_json_schema_object_fields(
|
||||||
|
resolve_references(filepath, req_obj),
|
||||||
|
include_parents=True,
|
||||||
|
)
|
||||||
|
|
||||||
if req_tables > 1:
|
if req_tables > 1:
|
||||||
for table in req_tables[1:]:
|
for table in req_tables[1:]:
|
||||||
|
@ -379,7 +426,10 @@ class MatrixUnits(Units):
|
||||||
elif res_type and Units.prop(good_response, "schema/properties"):
|
elif res_type and Units.prop(good_response, "schema/properties"):
|
||||||
# response is an object:
|
# response is an object:
|
||||||
schema = good_response["schema"]
|
schema = good_response["schema"]
|
||||||
res_tables = get_json_schema_object_fields(schema)
|
res_tables = get_json_schema_object_fields(
|
||||||
|
resolve_references(filepath, schema),
|
||||||
|
include_parents=True,
|
||||||
|
)
|
||||||
for table in res_tables:
|
for table in res_tables:
|
||||||
if "no-table" not in table:
|
if "no-table" not in table:
|
||||||
endpoint["res_tables"].append(table)
|
endpoint["res_tables"].append(table)
|
||||||
|
@ -445,13 +495,16 @@ class MatrixUnits(Units):
|
||||||
if not filename.endswith(".yaml"):
|
if not filename.endswith(".yaml"):
|
||||||
continue
|
continue
|
||||||
self.log("Reading swagger API: %s" % filename)
|
self.log("Reading swagger API: %s" % filename)
|
||||||
with open(os.path.join(path, filename), "r") as f:
|
filepath = os.path.join(path, filename)
|
||||||
|
with open(filepath, "r") as f:
|
||||||
# strip .yaml
|
# strip .yaml
|
||||||
group_name = filename[:-5].replace("-", "_")
|
group_name = filename[:-5].replace("-", "_")
|
||||||
if is_v2:
|
if is_v2:
|
||||||
group_name = "v2_" + group_name
|
group_name = "v2_" + group_name
|
||||||
api = yaml.load(f.read())
|
api = yaml.load(f.read())
|
||||||
api["__meta"] = self._load_swagger_meta(api, group_name)
|
api["__meta"] = self._load_swagger_meta(
|
||||||
|
filepath, api, group_name
|
||||||
|
)
|
||||||
apis[group_name] = api
|
apis[group_name] = api
|
||||||
return apis
|
return apis
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue