Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RFE: Add API to override Platform #706

Open
glensc opened this issue Mar 21, 2021 · 8 comments
Open

RFE: Add API to override Platform #706

glensc opened this issue Mar 21, 2021 · 8 comments

Comments

@glensc
Copy link
Contributor

glensc commented Mar 21, 2021

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:

  • # Plex Header Configuation
    X_PLEX_PROVIDES = CONFIG.get('header.provides', 'controller')
    X_PLEX_PLATFORM = CONFIG.get('header.platform', CONFIG.get('header.platorm', uname()[0]))
    X_PLEX_PLATFORM_VERSION = CONFIG.get('header.platform_version', uname()[2])
    X_PLEX_PRODUCT = CONFIG.get('header.product', PROJECT)
    X_PLEX_VERSION = CONFIG.get('header.version', VERSION)
    X_PLEX_DEVICE = CONFIG.get('header.device', X_PLEX_PLATFORM)
    X_PLEX_DEVICE_NAME = CONFIG.get('header.device_name', uname()[1])
    X_PLEX_IDENTIFIER = CONFIG.get('header.identifier', str(hex(getnode())))
    BASE_HEADERS = reset_base_headers()

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:

@Hellowlol
Copy link
Collaborator

Hellowlol commented Mar 21, 2021

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.

@glensc glensc changed the title Add API to override Platform RFE: Add API to override Platform Mar 21, 2021
@glensc
Copy link
Contributor Author

glensc commented Mar 21, 2021

@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.

@Hellowlol
Copy link
Collaborator

Hellowlol commented Mar 21, 2021

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. 😄

@glensc
Copy link
Contributor Author

glensc commented Mar 21, 2021

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
Copy link
Contributor Author

glensc commented Mar 21, 2021

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
Copy link
Contributor Author

glensc commented Mar 21, 2021

Started something:

need some kind of guidance on:

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

@glensc
Copy link
Contributor Author

glensc commented Mar 22, 2021

I found this when attempting to refactor:

  • def init_sync():
    import plexapi
    plexapi.X_PLEX_PROVIDES = 'sync-target'
    plexapi.BASE_HEADERS['X-Plex-Sync-Version'] = '2'
    plexapi.BASE_HEADERS['X-Plex-Provides'] = plexapi.X_PLEX_PROVIDES
    # mimic iPhone SE
    plexapi.X_PLEX_PLATFORM = 'iOS'
    plexapi.X_PLEX_PLATFORM_VERSION = '11.4.1'
    plexapi.X_PLEX_DEVICE = 'iPhone'
    plexapi.BASE_HEADERS['X-Plex-Platform'] = plexapi.X_PLEX_PLATFORM
    plexapi.BASE_HEADERS['X-Plex-Platform-Version'] = plexapi.X_PLEX_PLATFORM_VERSION
    plexapi.BASE_HEADERS['X-Plex-Device'] = plexapi.X_PLEX_DEVICE

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.

@JonnyWong16
Copy link
Collaborator

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants