python-plexapi icon indicating copy to clipboard operation
python-plexapi copied to clipboard

RFE: Add API to override Platform

Open glensc opened this issue 4 years ago • 8 comments

Describe the issue

There's currently no programmatic way to override Platform and Client name.

Hacks like overwriting X_PLEX_PLATFORM / X_PLEX_DEVICE_NAME do not work without more internal symbols hacking, because those values are copied elsewhere:

  • https://github.com/pkkid/python-plexapi/blob/1429867ae5b0bb92bc9db373f7dec36bc035b686/plexapi/init.py#L23-L32

Setting environment variables also does not work, as that needs to be done before the import plexapi is called.

Code snippets

from os import getenv, environ
import plexapi

        plex_config = {
            'PLEXAPI_HEADER_PLATFORM': 'PlexTraktSync',
            'PLEXAPI_HEADER_DEVICE_NAME': 'PlexTraktSync',
        }
        plexapi.X_PLEX_DEVICE_NAME = 'PlexTraktSync'
        for k, v in plex_config.items():
            environ[k] = v

Expected behavior

    plex = PlexServer(url, token, device_platform='PlexTraktSync')

Additional context

Trying to make changes identifiable to be able to skip own changes. I.e skip changes identified by named device:

  • https://github.com/Taxel/PlexTraktSync/discussions/146#discussioncomment-507487

glensc avatar Mar 21 '21 08:03 glensc

I don’t understand the problem. Your describing different ways to set this that does work. You have to do it in the correct order.

I also fail to see how the issue you linked to is relevant.

You need to fix this in your script.

Hellowlol avatar Mar 21 '21 12:03 Hellowlol

@Hellowlol those examples are all various hacks. Therefore I request a programmatic way to set the deviceId in the plex instance, not the global static module internal variable. Hence creating this issue for enchancement. Having some trickery done before importing a module trashes up project coding style. Python coding style is that you put import's in the beginning of the file, and then in main() you execute the code.

Besides messing up style, it's very fragile, if in case somebody else loads the module before the header overwrites the code, your initialization will fail.

glensc avatar Mar 21 '21 12:03 glensc

I can’t speak for others but I’m not gonna do this at all.

There are 3 ways to do this. Patching, environmental variables and using a config file.

Your assuming that PlexServer is the main entry point. That might be true for simple scripts, but what about all the others? Should we add device_platform to all other classes that ppl might, such as the cloud classes? I assume you see my point, as this will be very had to maintain.

With that being said, if you can come up with a simpler method then we are currently using that is easy to maintain I’ll happily merge that. 😄

Hellowlol avatar Mar 21 '21 13:03 Hellowlol

The problem with patching and environment variables is that these need to be done before 'import' statement. The problem with config, is that it's global and applies to all applications, not my application, so that's out of the way for setting application-specific properties.

The main problem seems to be around BASE_HEADERS being initialized at import plex. if that could be delayed, that would solve the problem (for me).

Perhaps move that BASE_HEADERS to new Config.getBaseHeaders() method (or getDefaultHeaders()), and instead of importing BASE_HEADERS in {client,myplex,server}.py, it is called from their respective constructor.

then applications like mine, can do CONFIG.set('header.platform', 'PlexTraktSync') before creating plex server instance.

Ideally, (i.e in the next iteration), the config could be passed to those {client,myplex,server} constructors.

glensc avatar Mar 21 '21 16:03 glensc

And yes, PlexServer was an example, and was setting only device_platform an example. the solution should apply to all properties. Unless you want Device and Client identification to become first citizen, in that case, I don't know that should be approached.

glensc avatar Mar 21 '21 16:03 glensc

Started something:

  • https://github.com/pkkid/python-plexapi/pull/707

need some kind of guidance on:

  1. how much compatibility is needed to keep
  2. how to name things

glensc avatar Mar 21 '21 18:03 glensc

I found this when attempting to refactor:

  • https://github.com/pkkid/python-plexapi/blob/2bde2344084721d7015167af4762d3bc397fe5d2/plexapi/sync.py#L8-L21

seems it's somewhat[*] documented how to override a device, just need to do both assignments.

plexapi.X_PLEX_PLATFORM = 'iOS' 
plexapi.BASE_HEADERS['X-Plex-Platform'] = plexapi.X_PLEX_PLATFORM 

[*] somewhat in sense, meaning it's not in docs, but source code, i.e not official.

glensc avatar Mar 22 '21 22:03 glensc

https://python-plexapi.readthedocs.io/en/latest/modules/sync.html#module-plexapi.sync

JonnyWong16 avatar Mar 22 '21 22:03 JonnyWong16