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

Basic custom helper functions in the Resource classes #14

Open
boxysean opened this issue Apr 14, 2016 · 4 comments
Open

Basic custom helper functions in the Resource classes #14

boxysean opened this issue Apr 14, 2016 · 4 comments

Comments

@boxysean
Copy link

I see that the way of getting the human name of a patient is handled in the FHIRClient class.

smart = client.FHIRClient(settings=my_settings)
r = Patient.where({'id': 1000})  # FHIRSearch object
results = r.perform(smart.server)  # Bundle object, two results
first_result = results.entry[0]
patient = first_result.resource
print smart.human_name(patient.name[0])

To me, this could naturally be a method of the Patient object, like this:

print patient.human_name

I'm interested in creating more functions like this, say what is the base title of on Observation object, which has no natural FHIR top-level field to represent it. For example, to me, the "title" of this resource is "Respiratory Rate" in the observation.code.text field (which is actually different for this resource, where I would say the "title" is "Weight Measured" in the observation.code.coding.display field).

Is this need very particular to how I'm applying it? How should I proceed?

  1. Create my own wrapping library, or
  2. Bring the discussion to the FHIR standards committee, or
  3. Improve the python client to allow for these functions to exist. Maybe a plug-in framework?
@boxysean boxysean changed the title Basic helper functions in the pyclient Resource classes Basic custom helper functions in the Resource classes Apr 14, 2016
@p2
Copy link
Member

p2 commented Apr 15, 2016

Yes, this is definitely desired and should live in the Python client (of course, nothing stops you from creating your own one ;) ). Thing is, all model classes are auto-generated from the spec using fhir-parser, hence it's a problem to create these methods on the resource classes themselves. In the Swift library we use class extensions for this purpose, Python doesn't have those, though. How do you think this could be solved?

@boxysean
Copy link
Author

Yeah, I'm aware of the relationship between the fhir-parser and the client-py. I believe it would be nice to have what I'm suggesting live outside the fhir-parser process -- what do you think?

Can you show me an example the class extensions in Swift? I'm not familiar with the language but I could probably get a gist of it if I see it. Does that live outside the fhir-parser process?

How Airflow does it

Last week I used Airflow's plugin framework. The user specifies a plugin directory, and the code from the folder is dynamically imported and plugged into the proper places. For example, I can make an extra Flask Admin View (a pretty standard Flask thing to do) and plug it to Airflow's Flask Admin framework, which provides menu links to the View and means to render it with a custom URL. Here's a rough sketch:

# file: plugin_folder/my_plugin.py
# code gets loaded by the Airflow plugin framework

class MyFlaskAdminView(flask_admin.view):
   def view(self, request):
       '''do stuff'''

class MyPlugin(airflow.plugin):
    flask_admin_views = [MyFlaskAdminView()]
    other_plugin_elements = [MyOtherPluginElement()]

Note: I'm not saying we should do it the Airflow way, just adding it as an example in. It depends on what kind of behavior to evoke.

Possible behaviors:

  1. The client-py library provides "extra" non-fhir-schema functionality on top of the raw FHIR models, such as patient.human_name.
  2. The client-py library end-user specifies extra functionality for their own programs and should not contribute those back to the client-py as it's specific to their use-case.
  3. Both 1 and 2 are supported, with a path to contribute generic plugins into a "contrib" or "core" part of the client-py library.

Regardless of the behaviors, it sounds to me like the auto-generated model classes may need some dynamic loading aspect to decouple the process of regenerating the FHIR classes from the process of developing non-fhir-schema functionality.

@p2
Copy link
Member

p2 commented Apr 17, 2016

Swift allows to extend classes, adding methods to classes that are globally available without the need to create a subclass. Here's an example of how our Swift client adds reference resolving to the generated Reference class.

I haven't used Airflow, but have used Yapsy which seems to function similarly. What I'm missing is how these plugins would enable to extend the classes, how would I be able to add the method/property human_name to the generated Patient class? So I'm looking for a way to solve your point 1, adding extra functionality to the generated classes.

@teffalump
Copy link

teffalump commented Apr 24, 2016

I suppose once the standard becomes mostly non-volatile, this issue becomes less complex. From what I gather, you are asking about monkey patching.

EDIT: An example.

from classes import Patient

def human_name(self):
    return self.code.coding.display

Patient.human_name = human_name
test=Patient()
test.human_name()
.... #do other stuff with it

Sounds like monkey patching a property gets into somewhat uncomfortable territory. Still possible, I think:

...same as before...

Patient.human_name = property(human_name)
test=Patient()
test.human_name
.... #should get the value

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

4 participants