Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Platypush
platypush
Commits
fdf6d8fb
Verified
Commit
fdf6d8fb
authored
Mar 03, 2022
by
Fabio Manganiello
Browse files
Better auto-generated documentation and fixed docstring warnings
parent
7c9e9d28
Pipeline
#163
passed with stages
in 7 minutes and 31 seconds
Changes
12
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
docs/source/platypush/events/chat.slack.rst
View file @
fdf6d8fb
``
platypush.message.event.
chat.slack``
==============
========================
``chat.slack``
==============
.. automodule:: platypush.message.event.chat.slack
:members:
docs/source/platypush/events/dbus.rst
View file @
fdf6d8fb
``
platypush.message.event.
dbus``
========
========================
``dbus``
========
.. automodule:: platypush.message.event.dbus
:members:
docs/source/platypush/events/gotify.rst
View file @
fdf6d8fb
``
platypush.message.event.
gotify``
==========
========================
``gotify``
==========
.. automodule:: platypush.message.event.gotify
:members:
docs/source/platypush/events/irc.rst
View file @
fdf6d8fb
``
platypush.message.event.
irc``
=======
========================
``irc``
=======
.. automodule:: platypush.message.event.irc
:members:
docs/source/platypush/events/ngrok.rst
View file @
fdf6d8fb
``
platypush.message.event.
ngrok``
=========
========================
``ngrok``
=========
.. automodule:: platypush.message.event.ngrok
:members:
docs/source/platypush/events/rss.rst
View file @
fdf6d8fb
``
platypush.message.event.
rss``
=======
========================
``rss``
=======
.. automodule:: platypush.message.event.rss
:members:
docs/source/platypush/events/sun.rst
View file @
fdf6d8fb
``
platypush.message.event.
sun``
=======
========================
``sun``
=======
.. automodule:: platypush.message.event.sun
:members:
docs/source/platypush/plugins/media.jellyfin.rst
View file @
fdf6d8fb
``media.jellyfin``
==================
==============
==================
.. automodule:: platypush.plugins.media.jellyfin
:members:
...
...
generate_missing_docs.py
View file @
fdf6d8fb
import
inspect
import
os
from
platypush.backend
import
Backend
...
...
@@ -6,11 +7,17 @@ from platypush.plugins import Plugin
from
platypush.utils.manifest
import
get_manifests
def
_get_inspect_plugin
():
p
=
get_plugin
(
'inspect'
)
assert
p
,
'Could not load the `inspect` plugin'
return
p
def
get_all_plugins
():
manifests
=
{
mf
.
component_name
for
mf
in
get_manifests
(
Plugin
)}
return
{
plugin_name
:
plugin_info
for
plugin_name
,
plugin_info
in
get_
plugin
(
'inspect'
).
get_all_plugins
().
output
.
items
()
for
plugin_name
,
plugin_info
in
_
get_
inspect_plugin
(
).
get_all_plugins
().
output
.
items
()
if
plugin_name
in
manifests
}
...
...
@@ -19,17 +26,17 @@ def get_all_backends():
manifests
=
{
mf
.
component_name
for
mf
in
get_manifests
(
Backend
)}
return
{
backend_name
:
backend_info
for
backend_name
,
backend_info
in
get_
plugin
(
'inspect'
).
get_all_backends
().
output
.
items
()
for
backend_name
,
backend_info
in
_
get_
inspect_plugin
(
).
get_all_backends
().
output
.
items
()
if
backend_name
in
manifests
}
def
get_all_events
():
return
get_
plugin
(
'inspect'
).
get_all_events
().
output
return
_
get_
inspect_plugin
(
).
get_all_events
().
output
def
get_all_responses
():
return
get_
plugin
(
'inspect'
).
get_all_responses
().
output
return
_
get_
inspect_plugin
(
).
get_all_responses
().
output
# noinspection DuplicatedCode
...
...
@@ -100,16 +107,17 @@ Backends
# noinspection DuplicatedCode
def
generate_events_doc
():
from
platypush.message
import
event
as
event_module
events_index
=
os
.
path
.
join
(
os
.
path
.
dirname
(
os
.
path
.
abspath
(
__file__
)),
'docs'
,
'source'
,
'events.rst'
)
events_dir
=
os
.
path
.
join
(
os
.
path
.
dirname
(
os
.
path
.
abspath
(
__file__
)),
'docs'
,
'source'
,
'platypush'
,
'events'
)
all_events
=
sorted
(
event
for
event
in
get_all_events
().
keys
())
all_events
=
sorted
(
event
for
event
in
get_all_events
().
keys
()
if
event
)
for
event
in
all_events
:
event_file
=
os
.
path
.
join
(
events_dir
,
event
[
len
(
'platypush.message.event.'
):]
+
'.rst'
)
event_file
=
os
.
path
.
join
(
events_dir
,
event
+
'.rst'
)
if
not
os
.
path
.
exists
(
event_file
):
header
=
'``{}``'
.
format
(
event
)
divider
=
'='
*
len
(
header
)
body
=
'
\n
.. automodule:: {}
\n
:members:
\n
'
.
format
(
event
)
body
=
'
\n
.. automodule::
{}.
{}
\n
:members:
\n
'
.
format
(
event_module
.
__name__
,
event
)
out
=
'
\n
'
.
join
([
header
,
divider
,
body
])
with
open
(
event_file
,
'w'
)
as
f
:
...
...
@@ -127,21 +135,22 @@ Events
'''
)
for
event
in
all_events
:
f
.
write
(
' platypush/events/'
+
event
[
len
(
'platypush.message.event.'
):]
+
'.rst
\n
'
)
f
.
write
(
' platypush/events/'
+
event
+
'.rst
\n
'
)
# noinspection DuplicatedCode
def
generate_responses_doc
():
from
platypush.message
import
response
as
response_module
responses_index
=
os
.
path
.
join
(
os
.
path
.
dirname
(
os
.
path
.
abspath
(
__file__
)),
'docs'
,
'source'
,
'responses.rst'
)
responses_dir
=
os
.
path
.
join
(
os
.
path
.
dirname
(
os
.
path
.
abspath
(
__file__
)),
'docs'
,
'source'
,
'platypush'
,
'responses'
)
all_responses
=
sorted
(
response
for
response
in
get_all_responses
().
keys
())
all_responses
=
sorted
(
response
for
response
in
get_all_responses
().
keys
()
if
response
)
for
response
in
all_responses
:
response_file
=
os
.
path
.
join
(
responses_dir
,
response
[
len
(
'platypush.message.response.'
):]
+
'.rst'
)
response_file
=
os
.
path
.
join
(
responses_dir
,
response
+
'.rst'
)
if
not
os
.
path
.
exists
(
response_file
):
header
=
'``{}``'
.
format
(
response
)
divider
=
'='
*
len
(
header
)
body
=
'
\n
.. automodule:: {}
\n
:members:
\n
'
.
format
(
response
)
body
=
'
\n
.. automodule::
{}.
{}
\n
:members:
\n
'
.
format
(
response_module
.
__name__
,
response
)
out
=
'
\n
'
.
join
([
header
,
divider
,
body
])
with
open
(
response_file
,
'w'
)
as
f
:
...
...
@@ -159,7 +168,7 @@ Responses
'''
)
for
response
in
all_responses
:
f
.
write
(
' platypush/responses/'
+
response
[
len
(
'platypush.message.response.'
):]
+
'.rst
\n
'
)
f
.
write
(
' platypush/responses/'
+
response
+
'.rst
\n
'
)
generate_plugins_doc
()
...
...
platypush/message/__init__.py
View file @
fdf6d8fb
...
...
@@ -71,7 +71,7 @@ class Message(object):
logger
.
warning
(
'Could not serialize object type {}: {}: {}'
.
format
(
type
(
obj
),
str
(
e
),
obj
))
def
__init__
(
self
,
timestamp
=
None
,
*
args
,
**
kwargs
):
def
__init__
(
self
,
timestamp
=
None
,
*
_
,
**
__
):
self
.
timestamp
=
timestamp
or
time
.
time
()
def
__str__
(
self
):
...
...
@@ -98,9 +98,9 @@ class Message(object):
def
parse
(
cls
,
msg
):
"""
Parse a generic message into a key-value dictionary
Params:
msg
--
Original message
-
can be a dictionary, a Message,
or a string/bytearray, as long as it's valid UTF-8 JSON
:param
msg
:
Original message
. It
can be a dictionary, a Message,
or a string/bytearray, as long as it's valid UTF-8 JSON
"""
if
isinstance
(
msg
,
cls
):
...
...
@@ -124,8 +124,8 @@ class Message(object):
def
build
(
cls
,
msg
):
"""
Builds a Message object from a dictionary.
Params:
msg
--
The message as a key-value dictionary, Message object or JSON string
:param
msg
:
The message as a key-value dictionary, Message object or JSON string
"""
from
platypush.utils
import
get_message_class_by_type
...
...
platypush/plugins/inspect/__init__.py
View file @
fdf6d8fb
...
...
@@ -4,6 +4,7 @@ import json
import
pkgutil
import
re
import
threading
from
abc
import
ABC
,
abstractmethod
from
typing
import
Optional
import
platypush.backend
# lgtm [py/import-and-import-from]
...
...
@@ -19,8 +20,7 @@ from platypush.message.response import Response
from
platypush.utils
import
get_decorators
# noinspection PyTypeChecker
class
Model
:
class
Model
(
ABC
):
def
__str__
(
self
):
return
json
.
dumps
(
dict
(
self
),
indent
=
2
,
sort_keys
=
True
)
...
...
@@ -37,6 +37,10 @@ class Model:
return
docutils
.
core
.
publish_parts
(
doc
,
writer_name
=
'html'
)[
'html_body'
]
@
abstractmethod
def
__iter__
(
self
):
raise
NotImplementedError
()
class
ProcedureEncoder
(
json
.
JSONEncoder
):
def
default
(
self
,
o
):
...
...
@@ -49,7 +53,7 @@ class ProcedureEncoder(json.JSONEncoder):
class
BackendModel
(
Model
):
def
__init__
(
self
,
backend
,
prefix
=
''
,
html_doc
:
bool
=
False
):
def
__init__
(
self
,
backend
,
prefix
=
''
,
html_doc
:
Optional
[
bool
]
=
False
):
self
.
name
=
backend
.
__module__
[
len
(
prefix
):]
self
.
html_doc
=
html_doc
self
.
doc
=
self
.
to_html
(
backend
.
__doc__
)
if
html_doc
and
backend
.
__doc__
else
backend
.
__doc__
...
...
@@ -60,11 +64,11 @@ class BackendModel(Model):
class
PluginModel
(
Model
):
def
__init__
(
self
,
plugin
,
prefix
=
''
,
html_doc
:
bool
=
False
):
def
__init__
(
self
,
plugin
,
prefix
=
''
,
html_doc
:
Optional
[
bool
]
=
False
):
self
.
name
=
plugin
.
__module__
[
len
(
prefix
):]
self
.
html_doc
=
html_doc
self
.
doc
=
self
.
to_html
(
plugin
.
__doc__
)
if
html_doc
and
plugin
.
__doc__
else
plugin
.
__doc__
self
.
actions
=
{
action_name
:
ActionModel
(
getattr
(
plugin
,
action_name
),
html_doc
=
html_doc
)
self
.
actions
=
{
action_name
:
ActionModel
(
getattr
(
plugin
,
action_name
),
html_doc
=
html_doc
or
False
)
for
action_name
in
get_decorators
(
plugin
,
climb_class_hierarchy
=
True
).
get
(
'action'
,
[])}
def
__iter__
(
self
):
...
...
@@ -77,8 +81,8 @@ class PluginModel(Model):
class
EventModel
(
Model
):
def
__init__
(
self
,
event
,
html_doc
:
bool
=
False
):
self
.
package
=
event
.
__module__
def
__init__
(
self
,
event
,
prefix
=
''
,
html_doc
:
Optional
[
bool
]
=
False
):
self
.
package
=
event
.
__module__
[
len
(
prefix
):]
self
.
name
=
event
.
__name__
self
.
html_doc
=
html_doc
self
.
doc
=
self
.
to_html
(
event
.
__doc__
)
if
html_doc
and
event
.
__doc__
else
event
.
__doc__
...
...
@@ -89,8 +93,8 @@ class EventModel(Model):
class
ResponseModel
(
Model
):
def
__init__
(
self
,
response
,
html_doc
:
bool
=
False
):
self
.
package
=
response
.
__module__
def
__init__
(
self
,
response
,
prefix
=
''
,
html_doc
:
Optional
[
bool
]
=
False
):
self
.
package
=
response
.
__module__
[
len
(
prefix
):]
self
.
name
=
response
.
__name__
self
.
html_doc
=
html_doc
self
.
doc
=
self
.
to_html
(
response
.
__doc__
)
if
html_doc
and
response
.
__doc__
else
response
.
__doc__
...
...
@@ -187,7 +191,7 @@ class InspectPlugin(Plugin):
for
_
,
modname
,
_
in
pkgutil
.
walk_packages
(
path
=
package
.
__path__
,
prefix
=
prefix
,
onerror
=
lambda
x
:
None
):
onerror
=
lambda
_
:
None
):
try
:
module
=
importlib
.
import_module
(
modname
)
except
Exception
as
e
:
...
...
@@ -207,7 +211,7 @@ class InspectPlugin(Plugin):
for
_
,
modname
,
_
in
pkgutil
.
walk_packages
(
path
=
package
.
__path__
,
prefix
=
prefix
,
onerror
=
lambda
x
:
None
):
onerror
=
lambda
_
:
None
):
try
:
module
=
importlib
.
import_module
(
modname
)
except
Exception
as
e
:
...
...
@@ -226,7 +230,7 @@ class InspectPlugin(Plugin):
for
_
,
modname
,
_
in
pkgutil
.
walk_packages
(
path
=
package
.
__path__
,
prefix
=
prefix
,
onerror
=
lambda
x
:
None
):
onerror
=
lambda
_
:
None
):
try
:
module
=
importlib
.
import_module
(
modname
)
except
Exception
as
e
:
...
...
@@ -238,7 +242,7 @@ class InspectPlugin(Plugin):
continue
if
inspect
.
isclass
(
obj
)
and
issubclass
(
obj
,
Event
)
and
obj
!=
Event
:
event
=
EventModel
(
event
=
obj
,
html_doc
=
self
.
_html_doc
)
event
=
EventModel
(
event
=
obj
,
html_doc
=
self
.
_html_doc
,
prefix
=
prefix
)
if
event
.
package
not
in
self
.
_events
:
self
.
_events
[
event
.
package
]
=
{
event
.
name
:
event
}
else
:
...
...
@@ -250,7 +254,7 @@ class InspectPlugin(Plugin):
for
_
,
modname
,
_
in
pkgutil
.
walk_packages
(
path
=
package
.
__path__
,
prefix
=
prefix
,
onerror
=
lambda
x
:
None
):
onerror
=
lambda
_
:
None
):
try
:
module
=
importlib
.
import_module
(
modname
)
except
Exception
as
e
:
...
...
@@ -262,14 +266,14 @@ class InspectPlugin(Plugin):
continue
if
inspect
.
isclass
(
obj
)
and
issubclass
(
obj
,
Response
)
and
obj
!=
Response
:
response
=
ResponseModel
(
response
=
obj
,
html_doc
=
self
.
_html_doc
)
response
=
ResponseModel
(
response
=
obj
,
html_doc
=
self
.
_html_doc
,
prefix
=
prefix
)
if
response
.
package
not
in
self
.
_responses
:
self
.
_responses
[
response
.
package
]
=
{
response
.
name
:
response
}
else
:
self
.
_responses
[
response
.
package
][
response
.
name
]
=
response
@
action
def
get_all_plugins
(
self
,
html_doc
:
bool
=
None
):
def
get_all_plugins
(
self
,
html_doc
:
Optional
[
bool
]
=
None
):
"""
:param html_doc: If True then the docstring will be parsed into HTML (default: False)
"""
...
...
@@ -284,7 +288,7 @@ class InspectPlugin(Plugin):
})
@
action
def
get_all_backends
(
self
,
html_doc
:
bool
=
None
):
def
get_all_backends
(
self
,
html_doc
:
Optional
[
bool
]
=
None
):
"""
:param html_doc: If True then the docstring will be parsed into HTML (default: False)
"""
...
...
@@ -299,7 +303,7 @@ class InspectPlugin(Plugin):
})
@
action
def
get_all_events
(
self
,
html_doc
:
bool
=
None
):
def
get_all_events
(
self
,
html_doc
:
Optional
[
bool
]
=
None
):
"""
:param html_doc: If True then the docstring will be parsed into HTML (default: False)
"""
...
...
@@ -311,13 +315,13 @@ class InspectPlugin(Plugin):
return
json
.
dumps
({
package
:
{
name
:
dict
(
event
)
for
name
,
event
in
self
.
_events
[
package
]
.
items
()
for
name
,
event
in
events
.
items
()
}
for
package
,
events
in
self
.
_events
.
items
()
})
@
action
def
get_all_responses
(
self
,
html_doc
:
bool
=
None
):
def
get_all_responses
(
self
,
html_doc
:
Optional
[
bool
]
=
None
):
"""
:param html_doc: If True then the docstring will be parsed into HTML (default: False)
"""
...
...
@@ -329,9 +333,9 @@ class InspectPlugin(Plugin):
return
json
.
dumps
({
package
:
{
name
:
dict
(
event
)
for
name
,
event
in
self
.
_
responses
[
package
]
.
items
()
for
name
,
event
in
responses
.
items
()
}
for
package
,
event
s
in
self
.
_responses
.
items
()
for
package
,
response
s
in
self
.
_responses
.
items
()
})
@
action
...
...
@@ -342,7 +346,7 @@ class InspectPlugin(Plugin):
return
json
.
loads
(
json
.
dumps
(
Config
.
get_procedures
(),
cls
=
ProcedureEncoder
))
@
action
def
get_config
(
self
,
entry
:
Optional
[
str
]
=
None
)
->
dict
:
def
get_config
(
self
,
entry
:
Optional
[
str
]
=
None
)
->
Optional
[
dict
]
:
"""
Return the configuration of the application or of a section.
...
...
platypush/plugins/media/jellyfin/__init__.py
View file @
fdf6d8fb
...
...
@@ -182,7 +182,7 @@ class MediaJellyfinPlugin(Plugin):
:param genres: Filter results by (a list of) genres.
:param tags: Filter results by (a list of) tags.
:param years: Filter results by (a list of) years.
:return: .. schema:: jellyfin.JellyfinArtistSchema(many=True)
:return: .. schema::
media.
jellyfin.JellyfinArtistSchema(many=True)
"""
return
self
.
_query
(
'/Artists'
,
schema_class
=
JellyfinArtistSchema
,
...
...
@@ -196,7 +196,7 @@ class MediaJellyfinPlugin(Plugin):
"""
Get the list of collections associated to the user on the server (Movies, Series, Channels etc.)
:return: .. schema:: jellyfin.JellyfinCollectionSchema(many=True)
:return: .. schema::
media.
jellyfin.JellyfinCollectionSchema(many=True)
"""
return
self
.
_query
(
f
'/Users/
{
self
.
_user_id
}
/Items'
,
...
...
@@ -242,6 +242,20 @@ class MediaJellyfinPlugin(Plugin):
:param genres: Filter results by (a list of) genres.
:param tags: Filter results by (a list of) tags.
:param years: Filter results by (a list of) years.
:return: The list of matching results.
Schema for artists:
.. schema:: media.jellyfin.JellyfinArtistSchema
Schema for collections:
.. schema:: media.jellyfin.JellyfinCollectionSchema
Schema for movies:
.. schema:: media.jellyfin.JellyfinMovieSchema
Schema for episodes:
.. schema:: media.jellyfin.JellyfinEpisodeSchema
"""
if
collection
:
collections
=
self
.
get_collections
().
output
# type: ignore
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment