├── tests ├── __init__.py ├── resources │ └── sample_settings.py ├── models_sqlAlchemy.py ├── test_models.py ├── test_config.py └── test_backends.py ├── fhirbug ├── models │ ├── __init__.py │ └── pagination.py ├── Fhir │ ├── base │ │ ├── __init__.py │ │ ├── template-codesystems.py │ │ ├── template-elementfactory.py │ │ ├── fhircontainedresource.py │ │ ├── fhirsearch_tests.py │ │ ├── settings.py │ │ ├── template-unittest.py │ │ ├── fhirdate.py │ │ ├── template-resource.py │ │ └── fhirreference.py │ ├── Resources │ │ ├── __init__.py │ │ ├── duration.py │ │ ├── age.py │ │ ├── distance.py │ │ ├── extensions │ │ │ └── __init__.py │ │ ├── count.py │ │ ├── money.py │ │ ├── element.py │ │ ├── narrative.py │ │ ├── range.py │ │ ├── backboneelement.py │ │ ├── contactdetail.py │ │ ├── period.py │ │ ├── ratio.py │ │ ├── codeableconcept.py │ │ ├── contributor.py │ │ ├── coding.py │ │ ├── resource.py │ │ ├── reference.py │ │ ├── binary.py │ │ ├── quantity.py │ │ ├── expression.py │ │ ├── annotation.py │ │ ├── contactpoint.py │ │ ├── domainresource.py │ │ ├── parameterdefinition.py │ │ ├── humanname.py │ │ ├── sampleddata.py │ │ ├── relatedartifact.py │ │ ├── attachment.py │ │ ├── meta.py │ │ ├── identifier.py │ │ ├── population.py │ │ ├── basic.py │ │ ├── medicinalproductundesirableeffect.py │ │ ├── enrollmentrequest.py │ │ ├── fhirdate.py │ │ ├── usagecontext.py │ │ ├── enrollmentresponse.py │ │ ├── signature.py │ │ ├── bodysite.py │ │ ├── linkage.py │ │ ├── address.py │ │ ├── productshelflife.py │ │ ├── flag.py │ │ ├── schedule.py │ │ ├── researchsubject.py │ │ ├── bodystructure.py │ │ ├── appointmentresponse.py │ │ ├── triggerdefinition.py │ │ ├── medicinalproductmanufactured.py │ │ ├── operationoutcome.py │ │ ├── fhirreference.py │ │ └── marketingstatus.py │ ├── resources.py │ └── __init__.py ├── db │ ├── backends │ │ ├── pymodm │ │ │ ├── __init__.py │ │ │ ├── pagination.py │ │ │ └── models.py │ │ ├── DjangoORM │ │ │ ├── __init__.py │ │ │ ├── pagination.py │ │ │ └── models.py │ │ ├── SQLAlchemy │ │ │ ├── __init__.py │ │ │ ├── pagination.py │ │ │ ├── base.py │ │ │ └── models.py │ │ └── __init__.py │ └── __init__.py ├── __init__.py ├── server │ └── __init__.py ├── constants.py ├── config │ ├── default_settings.py │ └── __init__.py ├── utils.py └── exceptions.py ├── requirements.txt ├── examples └── pymodm_autogenerated │ ├── __init__.py │ ├── static │ └── GitHub-Mark-32px.png │ ├── docker-compose.yml │ ├── settings_prod.py │ ├── requirements.txt │ ├── settings.py │ ├── Dockerfile │ ├── tools │ ├── download_examples.py │ ├── generate_ref_types.py │ └── fhirloader.py │ └── flask_app.py ├── MANIFEST.in ├── .gitmodules ├── docs ├── examples │ ├── index.rst │ └── pymodm │ │ └── readme.rst ├── api_exceptions.rst ├── api_index.rst ├── overview.rst ├── api_attributes.rst ├── api_server.rst ├── api_mixins.rst ├── Makefile ├── make.bat ├── overview │ ├── creating_mappings.rst │ └── logging.rst └── index.rst ├── .readthedocs.yml ├── setup.py ├── .gitignore ├── .coveragerc ├── tools ├── generate_models.sh └── get_searchables.py ├── requirements-dev.txt ├── .travis.yml ├── LICENSE └── run_doctests.py /tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /fhirbug/models/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /fhirbug/Fhir/base/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /fhirbug/db/backends/pymodm/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | isodate==0.6.0 2 | -------------------------------------------------------------------------------- /examples/pymodm_autogenerated/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /fhirbug/Fhir/base/template-codesystems.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /fhirbug/__init__.py: -------------------------------------------------------------------------------- 1 | VERSION = '0.1.3' 2 | -------------------------------------------------------------------------------- /fhirbug/db/backends/DjangoORM/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /fhirbug/db/backends/SQLAlchemy/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | recursive-exclude fhirbug/tools * 2 | -------------------------------------------------------------------------------- /fhirbug/db/backends/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Database backends. 3 | """ 4 | -------------------------------------------------------------------------------- /tests/resources/sample_settings.py: -------------------------------------------------------------------------------- 1 | DEBUG = True 2 | 3 | TESTING = True 4 | -------------------------------------------------------------------------------- /fhirbug/db/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | This package wraps all db related modules. 3 | """ 4 | -------------------------------------------------------------------------------- /fhirbug/Fhir/Resources/__init__.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Auto generated FHIR Resource classes. 3 | ''' 4 | -------------------------------------------------------------------------------- /fhirbug/server/__init__.py: -------------------------------------------------------------------------------- 1 | from .requesthandlers import * 2 | from .requestparser import * 3 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "tools/fhir_parser"] 2 | path = tools/fhir_parser 3 | url = https://github.com/smart-on-fhir/fhir-parser.git 4 | -------------------------------------------------------------------------------- /docs/examples/index.rst: -------------------------------------------------------------------------------- 1 | Examples 2 | --------- 3 | 4 | .. toctree:: 5 | :maxdepth: 3 6 | :caption: Contents: 7 | 8 | pymodm/readme 9 | -------------------------------------------------------------------------------- /.readthedocs.yml: -------------------------------------------------------------------------------- 1 | build: 2 | image: latest 3 | 4 | python: 5 | version: 3.6 6 | setup_py_install: true 7 | 8 | requirements_file: requirements.txt 9 | -------------------------------------------------------------------------------- /docs/examples/pymodm/readme.rst: -------------------------------------------------------------------------------- 1 | PyMODM Autogenerated 2 | -------------------- 3 | 4 | 5 | .. include:: ../../../examples/pymodm_autogenerated/README.rst 6 | -------------------------------------------------------------------------------- /docs/api_exceptions.rst: -------------------------------------------------------------------------------- 1 | fhirbug.exceptions 2 | =================== 3 | 4 | 5 | .. automodule:: fhirbug.exceptions 6 | :members: 7 | :inherited-members: 8 | -------------------------------------------------------------------------------- /examples/pymodm_autogenerated/static/GitHub-Mark-32px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zensoup/fhirbug/HEAD/examples/pymodm_autogenerated/static/GitHub-Mark-32px.png -------------------------------------------------------------------------------- /fhirbug/constants.py: -------------------------------------------------------------------------------- 1 | 2 | # Audit Event Outcomes 3 | AUDIT_SUCCESS = "0" 4 | AUDIT_MINOR_FAILURE = "4" 5 | AUDIT_SERIOUS_FAILURE = "8" 6 | AUDIT_MAJOR_FAILURE = "12" 7 | -------------------------------------------------------------------------------- /docs/api_index.rst: -------------------------------------------------------------------------------- 1 | .. _api: 2 | 3 | API 4 | === 5 | 6 | .. toctree:: 7 | :maxdepth: 2 8 | :caption: Contents: 9 | 10 | api_attributes 11 | api_mixins 12 | api_server 13 | api_exceptions 14 | -------------------------------------------------------------------------------- /examples/pymodm_autogenerated/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | services: 3 | web: 4 | build: . 5 | ports: 6 | - "5000:5000" 7 | depends_on: 8 | - mongo 9 | mongo: 10 | image: "mongo:4" 11 | -------------------------------------------------------------------------------- /docs/overview.rst: -------------------------------------------------------------------------------- 1 | .. _overview: 2 | 3 | 4 | Overview 5 | ======== 6 | 7 | .. toctree:: 8 | :maxdepth: 3 9 | :caption: Contents: 10 | 11 | overview/creating_mappings 12 | overview/fhir_resources 13 | overview/auditing 14 | overview/logging 15 | -------------------------------------------------------------------------------- /examples/pymodm_autogenerated/settings_prod.py: -------------------------------------------------------------------------------- 1 | # 2 | # Database 3 | # 4 | DB_BACKEND = "pymodm" 5 | PYMODM_CONFIG = {"URI": "mongodb://mongo:27017/fhirbug"} 6 | # 7 | # Search 8 | # 9 | DEFAULT_BUNDLE_SIZE = 20 10 | MAX_BUNDLE_SIZE = 100 11 | 12 | MODELS_PATH = "mappings" 13 | 14 | DEBUG = False 15 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup, find_packages 2 | 3 | setup( 4 | name="fhirbug", 5 | version="0.1.1", 6 | packages=find_packages(), 7 | author="Vangelis Kostalas", 8 | author_email="kostalas.v@gmail.com", 9 | description="A Fhir server", 10 | python_requires=">=3.6", 11 | ) 12 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | .idea 3 | build* 4 | __pycache__ 5 | table_fields.py 6 | /*.egg-info 7 | /*.egg 8 | /dist/ 9 | flask_app.py 10 | main.py 11 | settings.py 12 | .gitignore 13 | flask_app.py 14 | main.py 15 | /models.py 16 | settings.py 17 | README.pdf 18 | docs/_build/ 19 | examples 20 | .pre-commit-config.yaml 21 | -------------------------------------------------------------------------------- /examples/pymodm_autogenerated/requirements.txt: -------------------------------------------------------------------------------- 1 | dicttoxml==1.7.4 2 | Flask==1.0.2 3 | isodate==0.6.0 4 | itsdangerous==1.1.0 5 | Jinja2==2.10 6 | Pygments==2.3.0 7 | pymodm==0.4.1 8 | pymongo==3.7.2 9 | requests==2.21.0 10 | six==1.12.0 11 | urllib3==1.24.1 12 | Werkzeug==0.15.3 13 | isodate==0.6.0 14 | gunicorn==19.9.0 15 | -------------------------------------------------------------------------------- /examples/pymodm_autogenerated/settings.py: -------------------------------------------------------------------------------- 1 | # 2 | # Database 3 | # 4 | DB_BACKEND = "pymodm" 5 | PYMODM_CONFIG = {"URI": "mongodb://localhost:27017/fhirbug2"} 6 | # 7 | # Search 8 | # 9 | DEFAULT_BUNDLE_SIZE = 20 10 | MAX_BUNDLE_SIZE = 100 11 | 12 | MODELS_PATH = "examples.pymodm_autogenerated.mappings" 13 | 14 | DEBUG = True 15 | -------------------------------------------------------------------------------- /.coveragerc: -------------------------------------------------------------------------------- 1 | [run] 2 | branch = True 3 | source = fhirbug 4 | 5 | [report] 6 | exclude_lines = 7 | if self.debug: 8 | pragma: no cover 9 | raise NotImplementedError 10 | if __name__ == .__main__.: 11 | ignore_errors = True 12 | omit = 13 | tests/* 14 | fhirbug/Fhir/* 15 | 16 | [html] 17 | directory = cover 18 | -------------------------------------------------------------------------------- /fhirbug/Fhir/resources.py: -------------------------------------------------------------------------------- 1 | ''' 2 | This file is dynamicaly populated by this module's __init__.py, so it's 3 | normal to see absolutely nothing in it. 4 | There isn't really much else to say here, this is starting to get a bit awkward... 5 | 6 | I wonder if I can can use the module's dynamic contents in doctests 7 | 8 | >>> p = Patient() 9 | 10 | ''' 11 | -------------------------------------------------------------------------------- /tools/generate_models.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # if [ ! -e fhir-parser ]; then 4 | # git submodule update --init --recursive 5 | # fi 6 | 7 | TOOLS_DIR=$(dirname "$0") 8 | cd $TOOLS_DIR 9 | source fhir_parser/.venv/bin/activate 10 | 11 | cp ../fhirbug/Fhir/base/settings.py fhir_parser/settings.py 12 | cd fhir_parser 13 | ./generate.py $1 14 | cd .. 15 | -------------------------------------------------------------------------------- /docs/api_attributes.rst: -------------------------------------------------------------------------------- 1 | .. _attributes: 2 | 3 | Attributes 4 | ========== 5 | 6 | .. automodule:: fhirbug.models.attributes 7 | :members: 8 | :inherited-members: 9 | 10 | 11 | .. .. autoclass:: Attribute 12 | .. :members: 13 | .. :inherited-members: 14 | .. 15 | .. .. autoclass:: const 16 | .. :members: 17 | .. :inherited-members: 18 | -------------------------------------------------------------------------------- /docs/api_server.rst: -------------------------------------------------------------------------------- 1 | fhirbug.server 2 | =============== 3 | 4 | 5 | Request Parsing 6 | --------------- 7 | 8 | .. automodule:: fhirbug.server.requestparser 9 | :members: 10 | :inherited-members: 11 | 12 | 13 | Request Handling 14 | ---------------- 15 | 16 | .. automodule:: fhirbug.server.requesthandlers 17 | :members: 18 | :inherited-members: 19 | -------------------------------------------------------------------------------- /docs/api_mixins.rst: -------------------------------------------------------------------------------- 1 | Mixins 2 | ====== 3 | 4 | .. automodule:: fhirbug.models.mixins 5 | :members: 6 | :inherited-members: 7 | 8 | .. .. autoclass:: fhirbug.models.mixins.FhirAbstractBaseMixin 9 | .. :members: 10 | .. :inherited-members: 11 | .. 12 | .. .. autoclass:: fhirbug.models.mixins.FhirBaseModelMixin 13 | .. :members: 14 | .. :inherited-members: 15 | -------------------------------------------------------------------------------- /tools/get_searchables.py: -------------------------------------------------------------------------------- 1 | import json 2 | import os 3 | 4 | 5 | j = None 6 | searchables = {} 7 | 8 | path = os.path.dirname(os.path.abspath(__file__)) 9 | with open (os.path.join(path, 'fhir_parser/downloads/search-parameters.json'), 'r') as f: 10 | j = json.loads(f.read()) 11 | 12 | for entry in j['entry']: 13 | resource = entry['resource'] 14 | for base in resource['base']: 15 | searchables[base] = searchables.get(base, []) + [resource['name']] 16 | 17 | import pprint 18 | pprint.pprint(searchables) 19 | -------------------------------------------------------------------------------- /tests/models_sqlAlchemy.py: -------------------------------------------------------------------------------- 1 | from fhirbug.models.mixins import FhirBaseModelMixin, FhirAbstractBaseMixin 2 | from sqlalchemy.ext.declarative import declarative_base 3 | from sqlalchemy import Column, Integer, String, ForeignKey 4 | 5 | Base = declarative_base() 6 | 7 | 8 | class DatabaseModel(Base, FhirAbstractBaseMixin, FhirBaseModelMixin): 9 | __tablename__ = "test" 10 | 11 | id = Column(Integer, primary_key=True) 12 | name = Column(String) 13 | fullname = Column(String) 14 | password = Column(String) 15 | -------------------------------------------------------------------------------- /fhirbug/db/backends/pymodm/pagination.py: -------------------------------------------------------------------------------- 1 | from fhirbug.models.pagination import Page 2 | 3 | 4 | def paginate(query, page, page_size): 5 | """ 6 | Implement pagination for Django ORM. 7 | """ 8 | if page <= 0: 9 | raise AttributeError("page needs to be >= 1") 10 | if page_size <= 0: 11 | raise AttributeError("page_size needs to be >= 1") 12 | items = query.limit(page_size).skip((page - 1) * page_size).all() 13 | total = query.count() 14 | return Page(list(items), page, page_size, total) 15 | -------------------------------------------------------------------------------- /fhirbug/db/backends/SQLAlchemy/pagination.py: -------------------------------------------------------------------------------- 1 | from fhirbug.models.pagination import Page 2 | 3 | 4 | def paginate(query, page, page_size): 5 | """ 6 | Implement pagination for SQLAlchemy. 7 | """ 8 | if page <= 0: 9 | raise AttributeError("page needs to be >= 1") 10 | if page_size <= 0: 11 | raise AttributeError("page_size needs to be >= 1") 12 | items = query.limit(page_size).offset((page - 1) * page_size).all() 13 | total = query.order_by(None).count() 14 | return Page(items, page, page_size, total) 15 | -------------------------------------------------------------------------------- /examples/pymodm_autogenerated/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.6-alpine 2 | 3 | RUN apk update && \ 4 | apk upgrade && \ 5 | apk add git 6 | ADD . /code 7 | WORKDIR /code 8 | RUN pip install -r requirements.txt 9 | RUN pip install git+https://github.com/zensoup/fhirbug 10 | RUN mv settings_prod.py settings.py 11 | 12 | CMD python tools/download_examples.py && \ 13 | python generate_examples.py -w && \ 14 | gunicorn --workers=4 --bind 0.0.0.0:5000 flask_app:app 15 | 16 | # Uncomment this line to skip example generation 17 | # CMD [ "python", "./flask_app.py" ] 18 | -------------------------------------------------------------------------------- /fhirbug/db/backends/DjangoORM/pagination.py: -------------------------------------------------------------------------------- 1 | from django.core.paginator import Paginator 2 | from fhirbug.models.pagination import Page 3 | 4 | 5 | def paginate(query, page, page_size): 6 | """ 7 | Implement pagination for Django ORM. 8 | """ 9 | if page <= 0: 10 | raise AttributeError("page needs to be >= 1") 11 | if page_size <= 0: 12 | raise AttributeError("page_size needs to be >= 1") 13 | items = query.all() 14 | paginator = Paginator(items, page_size) 15 | items = paginator.get_page(page) 16 | total = query.count() 17 | return Page(items, page, page_size, total) 18 | -------------------------------------------------------------------------------- /requirements-dev.txt: -------------------------------------------------------------------------------- 1 | alabaster==0.7.12 2 | Babel==2.6.0 3 | certifi==2018.11.29 4 | chardet==3.0.4 5 | Click==7.0 6 | coverage==4.5.2 7 | Django>=2.1.6 8 | docutils==0.14 9 | Flask==1.0.2 10 | idna==2.8 11 | imagesize==1.1.0 12 | isodate==0.6.0 13 | itsdangerous==1.1.0 14 | Jinja2==2.10 15 | MarkupSafe==1.1.0 16 | nose==1.3.7 17 | packaging==18.0 18 | Pygments==2.3.0 19 | pymodm==0.4.1 20 | pymongo==3.7.2 21 | pyparsing==2.3.0 22 | pytz==2018.7 23 | requests==2.21.0 24 | six==1.12.0 25 | snowballstemmer==1.2.1 26 | Sphinx==1.8.2 27 | sphinxcontrib-websupport==1.1.0 28 | SQLAlchemy==1.2.15 29 | urllib3==1.24.1 30 | Werkzeug==0.14.1 31 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = sphinx-build 7 | SOURCEDIR = . 8 | BUILDDIR = _build 9 | 10 | # Put it first so that "make" without argument is like "make help". 11 | help: 12 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 13 | 14 | .PHONY: help Makefile 15 | 16 | # Catch-all target: route all unknown targets to Sphinx using the new 17 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 18 | %: Makefile 19 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 20 | -------------------------------------------------------------------------------- /examples/pymodm_autogenerated/tools/download_examples.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import argparse 3 | from types import SimpleNamespace 4 | 5 | from fhirloader import FHIRLoader 6 | 7 | FHIRLoader.needs = {"profiles-resources.json": "examples-json.zip"} 8 | 9 | 10 | parser = argparse.ArgumentParser() 11 | parser.add_argument("-f", "--force", help="Force re-downloading of the files", 12 | action="store_true") 13 | parser.add_argument("-t", "--target", help="Target directory", default="test_cache") 14 | 15 | args = parser.parse_args() 16 | force = args.force 17 | target = args.target 18 | 19 | print(f'Downloading examples to {target}') 20 | l = FHIRLoader( 21 | SimpleNamespace(specification_url="http://hl7.org/fhir/R4"), target 22 | ) 23 | l.load(force) 24 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | services: 3 | - mongodb 4 | python: 5 | - "3.6" 6 | - "3.7" 7 | sudo: required 8 | dist: xenial 9 | install: 10 | - pip install -r requirements-dev.txt 11 | - pip install codecov 12 | before_script: 13 | - python examples/pymodm_autogenerated/tools/download_examples.py -t examples/pymodm_autogenerated/test_cache 14 | script: 15 | - coverage run run_doctests.py 16 | - nosetests --with-coverage --cover-package=fhirbug.server --cover-package=fhirbug.models --cover-package=fhirbug.db --cover-package=fhirbug.config -I fhirsearch_tests 17 | - nosetests -s --with-coverage --cover-package=fhirbug.server --cover-package=fhirbug.models --cover-package=fhirbug.db --cover-package=fhirbug.config -I fhirsearch_tests examples/pymodm_autogenerated/test_mongo_app.py 18 | 19 | after_success: 20 | - codecov 21 | -------------------------------------------------------------------------------- /fhirbug/Fhir/Resources/duration.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Generated from FHIR 4.0.0-a53ec6ee1b (http://hl7.org/fhir/StructureDefinition/Duration) on 2019-01-25. 5 | # 2019, SMART Health IT. 6 | ## 7 | 8 | 9 | from . import quantity 10 | 11 | class Duration(quantity.Quantity): 12 | """ A length of time. 13 | """ 14 | 15 | resource_type = "Duration" 16 | 17 | def __init__(self, jsondict=None, strict=True, **kwargs): 18 | """ Initialize all valid properties. 19 | 20 | :raises: FHIRValidationError on validation errors, unless strict is False 21 | :param dict jsondict: A JSON dictionary to use for initialization 22 | :param bool strict: If True (the default), invalid variables will raise a TypeError 23 | """ 24 | 25 | super(Duration, self).__init__(jsondict=jsondict, strict=strict, **kwargs) 26 | 27 | -------------------------------------------------------------------------------- /fhirbug/Fhir/Resources/age.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Generated from FHIR 4.0.0-a53ec6ee1b (http://hl7.org/fhir/StructureDefinition/Age) on 2019-01-25. 5 | # 2019, SMART Health IT. 6 | ## 7 | 8 | 9 | from . import quantity 10 | 11 | class Age(quantity.Quantity): 12 | """ A duration of time during which an organism (or a process) has existed. 13 | """ 14 | 15 | resource_type = "Age" 16 | 17 | def __init__(self, jsondict=None, strict=True, **kwargs): 18 | """ Initialize all valid properties. 19 | 20 | :raises: FHIRValidationError on validation errors, unless strict is False 21 | :param dict jsondict: A JSON dictionary to use for initialization 22 | :param bool strict: If True (the default), invalid variables will raise a TypeError 23 | """ 24 | 25 | super(Age, self).__init__(jsondict=jsondict, strict=strict, **kwargs) 26 | 27 | -------------------------------------------------------------------------------- /fhirbug/Fhir/Resources/distance.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Generated from FHIR 4.0.0-a53ec6ee1b (http://hl7.org/fhir/StructureDefinition/Distance) on 2019-01-25. 5 | # 2019, SMART Health IT. 6 | ## 7 | 8 | 9 | from . import quantity 10 | 11 | class Distance(quantity.Quantity): 12 | """ A length - a value with a unit that is a physical distance. 13 | """ 14 | 15 | resource_type = "Distance" 16 | 17 | def __init__(self, jsondict=None, strict=True, **kwargs): 18 | """ Initialize all valid properties. 19 | 20 | :raises: FHIRValidationError on validation errors, unless strict is False 21 | :param dict jsondict: A JSON dictionary to use for initialization 22 | :param bool strict: If True (the default), invalid variables will raise a TypeError 23 | """ 24 | 25 | super(Distance, self).__init__(jsondict=jsondict, strict=strict, **kwargs) 26 | 27 | -------------------------------------------------------------------------------- /docs/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | pushd %~dp0 4 | 5 | REM Command file for Sphinx documentation 6 | 7 | if "%SPHINXBUILD%" == "" ( 8 | set SPHINXBUILD=sphinx-build 9 | ) 10 | set SOURCEDIR=. 11 | set BUILDDIR=_build 12 | 13 | if "%1" == "" goto help 14 | 15 | %SPHINXBUILD% >NUL 2>NUL 16 | if errorlevel 9009 ( 17 | echo. 18 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx 19 | echo.installed, then set the SPHINXBUILD environment variable to point 20 | echo.to the full path of the 'sphinx-build' executable. Alternatively you 21 | echo.may add the Sphinx directory to PATH. 22 | echo. 23 | echo.If you don't have Sphinx installed, grab it from 24 | echo.http://sphinx-doc.org/ 25 | exit /b 1 26 | ) 27 | 28 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% 29 | goto end 30 | 31 | :help 32 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% 33 | 34 | :end 35 | popd 36 | -------------------------------------------------------------------------------- /fhirbug/config/default_settings.py: -------------------------------------------------------------------------------- 1 | # Return tracebacks with OperationOutcomes when an exceprion occurs 2 | DEBUG = False 3 | 4 | # How many items should we include in budles whwn count is not specified 5 | DEFAULT_BUNDLE_SIZE = 20 6 | 7 | # Limit bundles to this size even if more are requested 8 | # TODO: Disable limiting when set to 0 9 | MAX_BUNDLE_SIZE = 100 10 | 11 | # Path to the models module 12 | MODELS_PATH = "models" 13 | 14 | # Which DB backend should be used 15 | # SQLAlchemy | DjangoORM | PyMODM 16 | DB_BACKEND = "SQLAlchemy" 17 | 18 | # Various settings related to how strictly the application handles 19 | # some situation. A value of True normally means that an error will be thrown 20 | STRICT_MODE = { 21 | # Throw or ignore attempts to set an attribute without having defined a setter func 22 | 'set_attribute_without_setter': False, 23 | # Throw when attempting to create a reference to an object that does not exist on the server 24 | 'set_non_existent_reference': False, 25 | } 26 | -------------------------------------------------------------------------------- /fhirbug/Fhir/Resources/extensions/__init__.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Subclasses of Fhir Resources that provide som functionality shortcuts. 3 | ''' 4 | 5 | from fhirbug.Fhir.Resources import bundle 6 | 7 | 8 | class PaginatedBundle(bundle.Bundle): 9 | def __init__(self, *args, pagination=None, **kwargs): 10 | ''' 11 | Override to accept a Pagination dict instead of a jsondict. 12 | ''' 13 | jsondict = None 14 | if 'jsondict' not in args and pagination: 15 | 16 | jsondict = { 17 | 'type': 'searchset', 18 | 'total': pagination['total'], 19 | 'entry': [{'resource': item} for item in pagination['items']], 20 | 'link': [], 21 | } 22 | if pagination['has_next']: 23 | jsondict['link'].append({'relation': 'next', 'url': pagination['next_page']}) 24 | if pagination['has_previous']: 25 | jsondict['link'].append({'relation': 'previous', 'url': pagination['previous_page']}) 26 | 27 | return super(PaginatedBundle, self).__init__(jsondict, *args, **kwargs) 28 | -------------------------------------------------------------------------------- /fhirbug/Fhir/base/template-elementfactory.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Generated from FHIR {{ info.version }} on {{ info.date }}. 5 | # {{ info.year }}, SMART Health IT. 6 | 7 | 8 | class FHIRElementFactory(object): 9 | """ Factory class to instantiate resources by resource name. 10 | """ 11 | 12 | @classmethod 13 | def instantiate(cls, resource_type, jsondict): 14 | """ Instantiate a resource of the type correlating to "resource_type". 15 | 16 | :param str resource_type: The name/type of the resource to instantiate 17 | :param dict jsondict: The JSON dictionary to use for data 18 | :returns: A resource of the respective type or `Element` 19 | """ 20 | {%- for klass in classes %}{% if klass.resource_type %} 21 | if "{{ klass.resource_type }}" == resource_type: 22 | from . import {{ klass.module }} 23 | return {{ klass.module }}.{{ klass.name }}(jsondict) 24 | {%- endif %}{% endfor %} 25 | from . import element 26 | return element.Element(jsondict) 27 | 28 | -------------------------------------------------------------------------------- /fhirbug/db/backends/SQLAlchemy/base.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from sqlalchemy import create_engine 4 | from sqlalchemy.orm import sessionmaker, scoped_session 5 | from sqlalchemy.ext.declarative import declarative_base, DeclarativeMeta 6 | 7 | from fhirbug.config import settings 8 | 9 | 10 | class AbstractModelMeta(DeclarativeMeta): 11 | def __getattribute__(self, item): 12 | if item == "query": 13 | if hasattr(self, "__get_query__"): 14 | query = super(AbstractModelMeta, self).__getattribute__("query") 15 | return self.__get_query__(self, query) 16 | return super(AbstractModelMeta, self).__getattribute__(item) 17 | 18 | 19 | Base = declarative_base(metaclass=AbstractModelMeta) 20 | 21 | # Create the db connection 22 | engine = create_engine(settings.SQLALCHEMY_CONFIG["URI"]) 23 | session = scoped_session(sessionmaker(bind=engine)) 24 | 25 | # Provide the base class for AbstractBaseClass to inherit 26 | # You must do this BEFORE importing any models 27 | Base.query = session.query_property() 28 | Base.session = property(lambda instance: session.object_session(instance)) 29 | -------------------------------------------------------------------------------- /fhirbug/Fhir/Resources/count.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Generated from FHIR 4.0.0-a53ec6ee1b (http://hl7.org/fhir/StructureDefinition/Count) on 2019-01-25. 5 | # 2019, SMART Health IT. 6 | ## 7 | 8 | 9 | from . import quantity 10 | 11 | class Count(quantity.Quantity): 12 | """ A measured or measurable amount. 13 | 14 | A measured amount (or an amount that can potentially be measured). Note 15 | that measured amounts include amounts that are not precisely quantified, 16 | including amounts involving arbitrary units and floating currencies. 17 | """ 18 | 19 | resource_type = "Count" 20 | 21 | def __init__(self, jsondict=None, strict=True, **kwargs): 22 | """ Initialize all valid properties. 23 | 24 | :raises: FHIRValidationError on validation errors, unless strict is False 25 | :param dict jsondict: A JSON dictionary to use for initialization 26 | :param bool strict: If True (the default), invalid variables will raise a TypeError 27 | """ 28 | 29 | super(Count, self).__init__(jsondict=jsondict, strict=strict, **kwargs) 30 | 31 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2018, Vangelis Kostalas. All rights reserved. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /fhirbug/Fhir/base/fhircontainedresource.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Class to hold contained resources until they are resolved. 5 | 6 | 7 | class FHIRContainedResource(object): 8 | """ Class to hold contained resources until they are resolved. 9 | 10 | The id of contained resources will be referenced from their parents as URL 11 | fragment, meaning "med1" will be referenced as "#med1". FHIRReference 12 | handles id normalization. 13 | 14 | http://hl7.org/implement/standards/fhir/references.html#contained 15 | """ 16 | 17 | def __init__(self, jsondict=None, owner=None): 18 | self.id = None 19 | self.type = None 20 | self.json = None 21 | self.owner = owner 22 | 23 | if jsondict is not None: 24 | self.update_with_json(jsondict) 25 | 26 | def update_with_json(self, jsondict): 27 | if jsondict is not None: 28 | self.id = jsondict.get('id') 29 | self.type = jsondict.get('resourceType') 30 | self.json = jsondict 31 | 32 | def as_json(self): 33 | return self.json 34 | -------------------------------------------------------------------------------- /tests/test_models.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from fhirbug.config import settings 3 | from sqlalchemy import create_engine 4 | from sqlalchemy.orm import sessionmaker, scoped_session 5 | from sqlalchemy.ext.declarative import declarative_base, DeclarativeMeta 6 | 7 | from . import models_sqlAlchemy 8 | 9 | 10 | session = None 11 | 12 | 13 | def setUpModule(): 14 | global session 15 | engine = create_engine("sqlite:///:memory:") 16 | Session = sessionmaker(bind=engine) 17 | session = Session() 18 | models_sqlAlchemy.Base.metadata.create_all(engine) 19 | session.add( 20 | models_sqlAlchemy.DatabaseModel( 21 | id=1, name="ion torrent", fullname="start", password="asas" 22 | ) 23 | ) 24 | session.commit() 25 | 26 | 27 | class TestModel(unittest.TestCase): 28 | def test_something(self): 29 | q = session.query(models_sqlAlchemy.DatabaseModel).all() 30 | 31 | # def test_getter_string(self): 32 | # """ 33 | # Getter can be a string representing the name of an attribute of _model 34 | # """ 35 | # inst = models.AttributeWithStringGetter() 36 | # 37 | # self.assertEquals(inst.name, "my_name") 38 | -------------------------------------------------------------------------------- /fhirbug/models/pagination.py: -------------------------------------------------------------------------------- 1 | import math 2 | 3 | 4 | class Page: 5 | """ 6 | Base class for holding paginated results along with pagination metadata. 7 | 8 | >>> p = Page([1]*20, 2, 20, 100) 9 | >>> p.has_next 10 | True 11 | >>> p.has_previous 12 | True 13 | >>> p.next_page 14 | 3 15 | >>> p.previous_page 16 | 1 17 | >>> p.pages 18 | 5 19 | 20 | 21 | >>> p = Page([1]*20, 1, 20, 100) 22 | >>> p.has_previous 23 | False 24 | >>> p.previous_page 25 | >>> p.pages 26 | 5 27 | 28 | >>> p = Page([1]*20, 5, 20, 100) 29 | >>> p.has_next 30 | False 31 | >>> p.has_previous 32 | True 33 | >>> p.next_page 34 | >>> p.previous_page 35 | 4 36 | >>> p.pages 37 | 5 38 | """ 39 | 40 | def __init__(self, items, page, page_size, total): 41 | self.items = items 42 | self.previous_page = None 43 | self.next_page = None 44 | self.has_previous = page > 1 45 | if self.has_previous: 46 | self.previous_page = page - 1 47 | previous_items = (page - 1) * page_size 48 | self.has_next = previous_items + len(items) < total 49 | if self.has_next: 50 | self.next_page = page + 1 51 | self.total = total 52 | self.pages = int(math.ceil(total / float(page_size))) 53 | -------------------------------------------------------------------------------- /fhirbug/Fhir/__init__.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Load all classes defined inside the Resources package 3 | and export them via the resources namespace. 4 | ''' 5 | import os 6 | import importlib 7 | import inspect 8 | 9 | from fhirbug.Fhir import resources 10 | from fhirbug.config import settings 11 | 12 | dir = os.path.dirname(__file__) 13 | for module_file in os.listdir(os.path.join(dir, 'Resources')): 14 | if module_file != '__init__.py' and module_file[-3:] == '.py': 15 | module_name = module_file[:-3] 16 | # TODO I would like this path to be dynamically retrieved but now is not the time 17 | module = importlib.import_module('fhirbug.Fhir.Resources.' + module_name) 18 | clsmembers = inspect.getmembers(module, inspect.isclass) 19 | for cls_name, cls in clsmembers: 20 | setattr(resources, cls_name, cls) 21 | 22 | # Import internal extensions 23 | int_module = importlib.import_module('fhirbug.Fhir.Resources.extensions') 24 | clsmembers = inspect.getmembers(int_module, inspect.isclass) 25 | for cls_name, cls in clsmembers: 26 | setattr(resources, cls_name, cls) 27 | 28 | # Import external extensions 29 | if hasattr(settings, 'EXTENSIONS_PATH'): 30 | ext_module = importlib.import_module(settings.EXTENSIONS_PATH) 31 | clsmembers = inspect.getmembers(ext_module, inspect.isclass) 32 | for cls_name, cls in clsmembers: 33 | setattr(resources, cls_name, cls) 34 | -------------------------------------------------------------------------------- /tests/test_config.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from unittest.mock import Mock 3 | from fhirbug.config import utils 4 | from .resources import sample_settings 5 | 6 | utils.default_settings = sample_settings 7 | 8 | 9 | class TestLazySettings(unittest.TestCase): 10 | def test_config_from_defaults(self): 11 | lazy_setting = utils.LazySettings() 12 | settings = lazy_setting._configure_from_defaults() 13 | self.assertIsInstance(settings, utils.FhirSettings) 14 | self.assertEquals(vars(settings), {"DEBUG": True, "TESTING": True}) 15 | 16 | def test_is_configured(self): 17 | lazy_setting = utils.LazySettings() 18 | self.assertFalse(lazy_setting.is_configured()) 19 | lazy_setting._configure_from_defaults() 20 | self.assertTrue(lazy_setting.is_configured()) 21 | 22 | def test_configure(self): 23 | class Mocked(utils.LazySettings): 24 | _configure_from_dict = Mock() 25 | _configure_from_path = Mock() 26 | _configure_from_defaults = Mock() 27 | 28 | lazy_setting = Mocked() 29 | 30 | test_settings = {"TEST": 5, "SOME": "OTHER", "ignored": True} 31 | lazy_setting.configure(test_settings) 32 | lazy_setting._configure_from_dict.assert_called_once_with(test_settings) 33 | lazy_setting._configure_from_path.assert_not_called() 34 | lazy_setting._configure_from_defaults.assert_not_called() 35 | -------------------------------------------------------------------------------- /fhirbug/Fhir/Resources/money.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Generated from FHIR 4.0.0-a53ec6ee1b (http://hl7.org/fhir/StructureDefinition/Money) on 2019-01-25. 5 | # 2019, SMART Health IT. 6 | ## 7 | 8 | 9 | from . import element 10 | 11 | class Money(element.Element): 12 | """ An amount of economic utility in some recognized currency. 13 | """ 14 | 15 | resource_type = "Money" 16 | 17 | def __init__(self, jsondict=None, strict=True, **kwargs): 18 | """ Initialize all valid properties. 19 | 20 | :raises: FHIRValidationError on validation errors, unless strict is False 21 | :param dict jsondict: A JSON dictionary to use for initialization 22 | :param bool strict: If True (the default), invalid variables will raise a TypeError 23 | """ 24 | 25 | self.currency = None 26 | """ ISO 4217 Currency Code. 27 | Type `str`. """ 28 | 29 | self.value = None 30 | """ Numerical value (with implicit precision). 31 | Type `float`. """ 32 | 33 | super(Money, self).__init__(jsondict=jsondict, strict=strict, **kwargs) 34 | 35 | def elementProperties(self): 36 | js = super(Money, self).elementProperties() 37 | js.extend([ 38 | ("currency", "currency", str, False, None, False), 39 | ("value", "value", float, False, None, False), 40 | ]) 41 | return js 42 | 43 | -------------------------------------------------------------------------------- /fhirbug/db/backends/pymodm/models.py: -------------------------------------------------------------------------------- 1 | from pymodm.errors import DoesNotExist 2 | from bson.objectid import ObjectId 3 | from bson.errors import InvalidId 4 | from fhirbug.db.backends.pymodm.pagination import paginate 5 | from fhirbug.models.mixins import FhirAbstractBaseMixin, FhirBaseModelMixin 6 | from fhirbug.exceptions import DoesNotExistError 7 | 8 | 9 | class AbstractBaseModel(FhirAbstractBaseMixin): 10 | """ 11 | The base class to provide functionality to 12 | our models. 13 | """ 14 | 15 | class Meta: 16 | abstract = True 17 | 18 | @classmethod 19 | def _get_orm_query(cls): 20 | return cls.objects 21 | 22 | @classmethod 23 | def _get_item_from_pk(cls, pk): 24 | try: 25 | return cls.objects.get({"_id": ObjectId(pk)}) 26 | except (DoesNotExist, InvalidId): 27 | raise DoesNotExistError(resource_type=cls.__name__, pk=pk) 28 | 29 | @classmethod 30 | def _delete_item(cls, item): 31 | item.delete() 32 | 33 | class FhirBaseModel(AbstractBaseModel, FhirBaseModelMixin): 34 | class Meta: 35 | abstract = True 36 | 37 | @classmethod 38 | def paginate(cls, *args, **kwargs): 39 | return paginate(*args, **kwargs) 40 | 41 | @classmethod 42 | def _after_create(cls, instance): 43 | instance.save() 44 | return instance 45 | 46 | @classmethod 47 | def _after_update(cls, instance): 48 | instance.save() 49 | return instance 50 | -------------------------------------------------------------------------------- /fhirbug/db/backends/DjangoORM/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | from fhirbug.db.backends.DjangoORM.pagination import paginate 3 | from fhirbug.models.mixins import FhirAbstractBaseMixin, FhirBaseModelMixin 4 | from fhirbug.exceptions import DoesNotExistError 5 | 6 | 7 | class AbstractBaseModel(models.Model, FhirAbstractBaseMixin): 8 | """ 9 | The base class to provide functionality to 10 | our models. 11 | """ 12 | 13 | class Meta: 14 | abstract = True 15 | 16 | @classmethod 17 | def _get_orm_query(cls): 18 | return cls.objects 19 | 20 | @classmethod 21 | def _get_item_from_pk(cls, pk): 22 | try: 23 | return cls.objects.get(pk=pk) 24 | except cls.DoesNotExist: 25 | raise DoesNotExistError(resource_type=cls.__name__, pk=pk) 26 | 27 | @classmethod 28 | def _delete_item(cls, item): 29 | item.delete() 30 | 31 | 32 | class FhirBaseModel(AbstractBaseModel, FhirBaseModelMixin): 33 | class Meta: 34 | abstract = True 35 | 36 | @classmethod 37 | def paginate(cls, *args, **kwargs): 38 | return paginate(*args, **kwargs) 39 | 40 | @classmethod 41 | def _after_create(cls, instance): 42 | try: 43 | instance.save() 44 | except Exception as e: 45 | raise e 46 | return instance 47 | 48 | @classmethod 49 | def _after_update(cls, instance): 50 | try: 51 | instance.save() 52 | except Exception as e: 53 | raise e 54 | return instance 55 | -------------------------------------------------------------------------------- /fhirbug/Fhir/Resources/element.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Generated from FHIR 4.0.0-a53ec6ee1b (http://hl7.org/fhir/StructureDefinition/Element) on 2019-01-25. 5 | # 2019, SMART Health IT. 6 | ## 7 | 8 | 9 | from . import fhirabstractbase 10 | 11 | class Element(fhirabstractbase.FHIRAbstractBase): 12 | """ Base for all elements. 13 | 14 | Base definition for all elements in a resource. 15 | """ 16 | 17 | resource_type = "Element" 18 | 19 | def __init__(self, jsondict=None, strict=True, **kwargs): 20 | """ Initialize all valid properties. 21 | 22 | :raises: FHIRValidationError on validation errors, unless strict is False 23 | :param dict jsondict: A JSON dictionary to use for initialization 24 | :param bool strict: If True (the default), invalid variables will raise a TypeError 25 | """ 26 | 27 | self.extension = None 28 | """ Additional content defined by implementations. 29 | List of `Extension` items (represented as `dict` in JSON). """ 30 | 31 | self.id = None 32 | """ Unique id for inter-element referencing. 33 | Type `str`. """ 34 | 35 | super(Element, self).__init__(jsondict=jsondict, strict=strict, **kwargs) 36 | 37 | def elementProperties(self): 38 | js = super(Element, self).elementProperties() 39 | from . import extension 40 | js.extend([ 41 | ("extension", "extension", extension.Extension, True, None, False), 42 | ("id", "id", str, False, None, False), 43 | ]) 44 | return js 45 | 46 | -------------------------------------------------------------------------------- /fhirbug/Fhir/Resources/narrative.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Generated from FHIR 4.0.0-a53ec6ee1b (http://hl7.org/fhir/StructureDefinition/Narrative) on 2019-01-25. 5 | # 2019, SMART Health IT. 6 | ## 7 | 8 | 9 | from . import element 10 | 11 | class Narrative(element.Element): 12 | """ Human-readable summary of the resource (essential clinical and business 13 | information). 14 | 15 | A human-readable summary of the resource conveying the essential clinical 16 | and business information for the resource. 17 | """ 18 | 19 | resource_type = "Narrative" 20 | 21 | def __init__(self, jsondict=None, strict=True, **kwargs): 22 | """ Initialize all valid properties. 23 | 24 | :raises: FHIRValidationError on validation errors, unless strict is False 25 | :param dict jsondict: A JSON dictionary to use for initialization 26 | :param bool strict: If True (the default), invalid variables will raise a TypeError 27 | """ 28 | 29 | self.div = None 30 | """ Limited xhtml content. 31 | Type `str`. """ 32 | 33 | self.status = None 34 | """ generated | extensions | additional | empty. 35 | Type `str`. """ 36 | 37 | super(Narrative, self).__init__(jsondict=jsondict, strict=strict, **kwargs) 38 | 39 | def elementProperties(self): 40 | js = super(Narrative, self).elementProperties() 41 | js.extend([ 42 | ("div", "div", str, False, None, True), 43 | ("status", "status", str, False, None, True), 44 | ]) 45 | return js 46 | 47 | -------------------------------------------------------------------------------- /run_doctests.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import doctest 3 | 4 | # The modules to be tested 5 | from fhirbug.Fhir.Resources import fhirabstractbase 6 | from fhirbug.Fhir.Resources import extensions 7 | from fhirbug.Fhir import resources 8 | from fhirbug.server import requestparser 9 | from fhirbug.db.backends import SQLAlchemy 10 | from fhirbug.models import attributes, pagination 11 | 12 | 13 | def testResourceContructor(verbose=False): 14 | 15 | # Create the extra globals 16 | context = {"Patient": resources.Patient, "Identifier": resources.Identifier} 17 | 18 | # Run the tests! 19 | doctest.testmod( 20 | fhirabstractbase, 21 | extraglobs=context, 22 | optionflags=doctest.NORMALIZE_WHITESPACE, 23 | verbose=verbose, 24 | ) 25 | doctest.testmod( 26 | extensions, 27 | extraglobs=context, 28 | optionflags=doctest.NORMALIZE_WHITESPACE, 29 | verbose=verbose, 30 | ) 31 | doctest.testmod( 32 | resources, optionflags=doctest.NORMALIZE_WHITESPACE, verbose=verbose 33 | ) 34 | doctest.testmod( 35 | requestparser, optionflags=doctest.NORMALIZE_WHITESPACE, verbose=verbose 36 | ) 37 | doctest.testmod( 38 | SQLAlchemy, optionflags=doctest.NORMALIZE_WHITESPACE, verbose=verbose 39 | ) 40 | doctest.testmod( 41 | attributes, optionflags=doctest.NORMALIZE_WHITESPACE, verbose=verbose 42 | ) 43 | doctest.testmod( 44 | pagination, optionflags=doctest.NORMALIZE_WHITESPACE, verbose=verbose 45 | ) 46 | 47 | 48 | if __name__ == "__main__": 49 | verbose = True if "-v" in sys.argv else False 50 | testResourceContructor(verbose) 51 | -------------------------------------------------------------------------------- /fhirbug/Fhir/Resources/range.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Generated from FHIR 4.0.0-a53ec6ee1b (http://hl7.org/fhir/StructureDefinition/Range) on 2019-01-25. 5 | # 2019, SMART Health IT. 6 | ## 7 | 8 | 9 | from . import element 10 | 11 | class Range(element.Element): 12 | """ Set of values bounded by low and high. 13 | 14 | A set of ordered Quantities defined by a low and high limit. 15 | """ 16 | 17 | resource_type = "Range" 18 | 19 | def __init__(self, jsondict=None, strict=True, **kwargs): 20 | """ Initialize all valid properties. 21 | 22 | :raises: FHIRValidationError on validation errors, unless strict is False 23 | :param dict jsondict: A JSON dictionary to use for initialization 24 | :param bool strict: If True (the default), invalid variables will raise a TypeError 25 | """ 26 | 27 | self.high = None 28 | """ High limit. 29 | Type `Quantity` (represented as `dict` in JSON). """ 30 | 31 | self.low = None 32 | """ Low limit. 33 | Type `Quantity` (represented as `dict` in JSON). """ 34 | 35 | super(Range, self).__init__(jsondict=jsondict, strict=strict, **kwargs) 36 | 37 | def elementProperties(self): 38 | js = super(Range, self).elementProperties() 39 | js.extend([ 40 | ("high", "high", quantity.Quantity, False, None, False), 41 | ("low", "low", quantity.Quantity, False, None, False), 42 | ]) 43 | return js 44 | 45 | 46 | import sys 47 | try: 48 | from . import quantity 49 | except ImportError: 50 | quantity = sys.modules[__package__ + '.quantity'] -------------------------------------------------------------------------------- /fhirbug/Fhir/Resources/backboneelement.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Generated from FHIR 4.0.0-a53ec6ee1b (http://hl7.org/fhir/StructureDefinition/BackboneElement) on 2019-01-25. 5 | # 2019, SMART Health IT. 6 | ## 7 | 8 | 9 | from . import element 10 | 11 | class BackboneElement(element.Element): 12 | """ Base for elements defined inside a resource. 13 | 14 | Base definition for all elements that are defined inside a resource - but 15 | not those in a data type. 16 | """ 17 | 18 | resource_type = "BackboneElement" 19 | 20 | def __init__(self, jsondict=None, strict=True, **kwargs): 21 | """ Initialize all valid properties. 22 | 23 | :raises: FHIRValidationError on validation errors, unless strict is False 24 | :param dict jsondict: A JSON dictionary to use for initialization 25 | :param bool strict: If True (the default), invalid variables will raise a TypeError 26 | """ 27 | 28 | self.modifierExtension = None 29 | """ Extensions that cannot be ignored even if unrecognized. 30 | List of `Extension` items (represented as `dict` in JSON). """ 31 | 32 | super(BackboneElement, self).__init__(jsondict=jsondict, strict=strict, **kwargs) 33 | 34 | def elementProperties(self): 35 | js = super(BackboneElement, self).elementProperties() 36 | js.extend([ 37 | ("modifierExtension", "modifierExtension", extension.Extension, True, None, False), 38 | ]) 39 | return js 40 | 41 | 42 | import sys 43 | try: 44 | from . import extension 45 | except ImportError: 46 | extension = sys.modules[__package__ + '.extension'] -------------------------------------------------------------------------------- /fhirbug/config/__init__.py: -------------------------------------------------------------------------------- 1 | import importlib 2 | from fhirbug.exceptions import ConfigurationError 3 | from fhirbug.config.utils import LazySettings 4 | 5 | 6 | settings = LazySettings() 7 | 8 | 9 | def import_models(): 10 | """ 11 | Dynamic import of the models module based on the backend selected in the configuration 12 | """ 13 | global settings 14 | if not settings: 15 | raise ConfigurationError( 16 | "Fhirbug settings have not been initialized. Use fhirbug.config.configure before using fhirbug." 17 | ) 18 | try: 19 | models_path = getattr(settings, "MODELS_PATH") 20 | except AttributeError: 21 | raise ConfigurationError("settings.MODELS_PATH has not been defined.") 22 | return importlib.import_module(models_path) 23 | 24 | 25 | def import_searches(): 26 | """ 27 | Dynamic import of the searches module based on the backend selected in the configuration 28 | """ 29 | global settings 30 | if not settings: 31 | raise ConfigurationError( 32 | "Fhirbug settings have not been initialized. Use fhirbug.config.configure before using fhirbug." 33 | ) 34 | try: 35 | db_backend = getattr(settings, "DB_BACKEND") 36 | except AttributeError: 37 | raise ConfigurationError("settings.DB_BACKEND has not been defined.") 38 | 39 | if db_backend.lower() == "sqlalchemy": 40 | return importlib.import_module("fhirbug.db.backends.SQLAlchemy.searches") 41 | elif db_backend.lower() == "djangoorm": 42 | return importlib.import_module("fhirbug.db.backends.DjangoORM.searches") 43 | elif db_backend.lower() == "pymodm": 44 | return importlib.import_module("fhirbug.db.backends.pymodm.searches") 45 | -------------------------------------------------------------------------------- /fhirbug/Fhir/Resources/contactdetail.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Generated from FHIR 4.0.0-a53ec6ee1b (http://hl7.org/fhir/StructureDefinition/ContactDetail) on 2019-01-25. 5 | # 2019, SMART Health IT. 6 | ## 7 | 8 | 9 | from . import element 10 | 11 | class ContactDetail(element.Element): 12 | """ Contact information. 13 | 14 | Specifies contact information for a person or organization. 15 | """ 16 | 17 | resource_type = "ContactDetail" 18 | 19 | def __init__(self, jsondict=None, strict=True, **kwargs): 20 | """ Initialize all valid properties. 21 | 22 | :raises: FHIRValidationError on validation errors, unless strict is False 23 | :param dict jsondict: A JSON dictionary to use for initialization 24 | :param bool strict: If True (the default), invalid variables will raise a TypeError 25 | """ 26 | 27 | self.name = None 28 | """ Name of an individual to contact. 29 | Type `str`. """ 30 | 31 | self.telecom = None 32 | """ Contact details for individual or organization. 33 | List of `ContactPoint` items (represented as `dict` in JSON). """ 34 | 35 | super(ContactDetail, self).__init__(jsondict=jsondict, strict=strict, **kwargs) 36 | 37 | def elementProperties(self): 38 | js = super(ContactDetail, self).elementProperties() 39 | js.extend([ 40 | ("name", "name", str, False, None, False), 41 | ("telecom", "telecom", contactpoint.ContactPoint, True, None, False), 42 | ]) 43 | return js 44 | 45 | 46 | import sys 47 | try: 48 | from . import contactpoint 49 | except ImportError: 50 | contactpoint = sys.modules[__package__ + '.contactpoint'] -------------------------------------------------------------------------------- /fhirbug/Fhir/Resources/period.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Generated from FHIR 4.0.0-a53ec6ee1b (http://hl7.org/fhir/StructureDefinition/Period) on 2019-01-25. 5 | # 2019, SMART Health IT. 6 | ## 7 | 8 | 9 | from . import element 10 | 11 | class Period(element.Element): 12 | """ Time range defined by start and end date/time. 13 | 14 | A time period defined by a start and end date and optionally time. 15 | """ 16 | 17 | resource_type = "Period" 18 | 19 | def __init__(self, jsondict=None, strict=True, **kwargs): 20 | """ Initialize all valid properties. 21 | 22 | :raises: FHIRValidationError on validation errors, unless strict is False 23 | :param dict jsondict: A JSON dictionary to use for initialization 24 | :param bool strict: If True (the default), invalid variables will raise a TypeError 25 | """ 26 | 27 | self.end = None 28 | """ End time with inclusive boundary, if not ongoing. 29 | Type `FHIRDate` (represented as `str` in JSON). """ 30 | 31 | self.start = None 32 | """ Starting time with inclusive boundary. 33 | Type `FHIRDate` (represented as `str` in JSON). """ 34 | 35 | super(Period, self).__init__(jsondict=jsondict, strict=strict, **kwargs) 36 | 37 | def elementProperties(self): 38 | js = super(Period, self).elementProperties() 39 | js.extend([ 40 | ("end", "end", fhirdate.FHIRDate, False, None, False), 41 | ("start", "start", fhirdate.FHIRDate, False, None, False), 42 | ]) 43 | return js 44 | 45 | 46 | import sys 47 | try: 48 | from . import fhirdate 49 | except ImportError: 50 | fhirdate = sys.modules[__package__ + '.fhirdate'] -------------------------------------------------------------------------------- /fhirbug/Fhir/Resources/ratio.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Generated from FHIR 4.0.0-a53ec6ee1b (http://hl7.org/fhir/StructureDefinition/Ratio) on 2019-01-25. 5 | # 2019, SMART Health IT. 6 | ## 7 | 8 | 9 | from . import element 10 | 11 | class Ratio(element.Element): 12 | """ A ratio of two Quantity values - a numerator and a denominator. 13 | 14 | A relationship of two Quantity values - expressed as a numerator and a 15 | denominator. 16 | """ 17 | 18 | resource_type = "Ratio" 19 | 20 | def __init__(self, jsondict=None, strict=True, **kwargs): 21 | """ Initialize all valid properties. 22 | 23 | :raises: FHIRValidationError on validation errors, unless strict is False 24 | :param dict jsondict: A JSON dictionary to use for initialization 25 | :param bool strict: If True (the default), invalid variables will raise a TypeError 26 | """ 27 | 28 | self.denominator = None 29 | """ Denominator value. 30 | Type `Quantity` (represented as `dict` in JSON). """ 31 | 32 | self.numerator = None 33 | """ Numerator value. 34 | Type `Quantity` (represented as `dict` in JSON). """ 35 | 36 | super(Ratio, self).__init__(jsondict=jsondict, strict=strict, **kwargs) 37 | 38 | def elementProperties(self): 39 | js = super(Ratio, self).elementProperties() 40 | js.extend([ 41 | ("denominator", "denominator", quantity.Quantity, False, None, False), 42 | ("numerator", "numerator", quantity.Quantity, False, None, False), 43 | ]) 44 | return js 45 | 46 | 47 | import sys 48 | try: 49 | from . import quantity 50 | except ImportError: 51 | quantity = sys.modules[__package__ + '.quantity'] -------------------------------------------------------------------------------- /fhirbug/Fhir/Resources/codeableconcept.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Generated from FHIR 4.0.0-a53ec6ee1b (http://hl7.org/fhir/StructureDefinition/CodeableConcept) on 2019-01-25. 5 | # 2019, SMART Health IT. 6 | ## 7 | 8 | 9 | from . import element 10 | 11 | class CodeableConcept(element.Element): 12 | """ Concept - reference to a terminology or just text. 13 | 14 | A concept that may be defined by a formal reference to a terminology or 15 | ontology or may be provided by text. 16 | """ 17 | 18 | resource_type = "CodeableConcept" 19 | 20 | def __init__(self, jsondict=None, strict=True, **kwargs): 21 | """ Initialize all valid properties. 22 | 23 | :raises: FHIRValidationError on validation errors, unless strict is False 24 | :param dict jsondict: A JSON dictionary to use for initialization 25 | :param bool strict: If True (the default), invalid variables will raise a TypeError 26 | """ 27 | 28 | self.coding = None 29 | """ Code defined by a terminology system. 30 | List of `Coding` items (represented as `dict` in JSON). """ 31 | 32 | self.text = None 33 | """ Plain text representation of the concept. 34 | Type `str`. """ 35 | 36 | super(CodeableConcept, self).__init__(jsondict=jsondict, strict=strict, **kwargs) 37 | 38 | def elementProperties(self): 39 | js = super(CodeableConcept, self).elementProperties() 40 | js.extend([ 41 | ("coding", "coding", coding.Coding, True, None, False), 42 | ("text", "text", str, False, None, False), 43 | ]) 44 | return js 45 | 46 | 47 | import sys 48 | try: 49 | from . import coding 50 | except ImportError: 51 | coding = sys.modules[__package__ + '.coding'] -------------------------------------------------------------------------------- /fhirbug/Fhir/Resources/contributor.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Generated from FHIR 4.0.0-a53ec6ee1b (http://hl7.org/fhir/StructureDefinition/Contributor) on 2019-01-25. 5 | # 2019, SMART Health IT. 6 | ## 7 | 8 | 9 | from . import element 10 | 11 | class Contributor(element.Element): 12 | """ Contributor information. 13 | 14 | A contributor to the content of a knowledge asset, including authors, 15 | editors, reviewers, and endorsers. 16 | """ 17 | 18 | resource_type = "Contributor" 19 | 20 | def __init__(self, jsondict=None, strict=True, **kwargs): 21 | """ Initialize all valid properties. 22 | 23 | :raises: FHIRValidationError on validation errors, unless strict is False 24 | :param dict jsondict: A JSON dictionary to use for initialization 25 | :param bool strict: If True (the default), invalid variables will raise a TypeError 26 | """ 27 | 28 | self.contact = None 29 | """ Contact details of the contributor. 30 | List of `ContactDetail` items (represented as `dict` in JSON). """ 31 | 32 | self.name = None 33 | """ Who contributed the content. 34 | Type `str`. """ 35 | 36 | self.type = None 37 | """ author | editor | reviewer | endorser. 38 | Type `str`. """ 39 | 40 | super(Contributor, self).__init__(jsondict=jsondict, strict=strict, **kwargs) 41 | 42 | def elementProperties(self): 43 | js = super(Contributor, self).elementProperties() 44 | js.extend([ 45 | ("contact", "contact", contactdetail.ContactDetail, True, None, False), 46 | ("name", "name", str, False, None, True), 47 | ("type", "type", str, False, None, True), 48 | ]) 49 | return js 50 | 51 | 52 | import sys 53 | try: 54 | from . import contactdetail 55 | except ImportError: 56 | contactdetail = sys.modules[__package__ + '.contactdetail'] -------------------------------------------------------------------------------- /examples/pymodm_autogenerated/tools/generate_ref_types.py: -------------------------------------------------------------------------------- 1 | """ 2 | Parse all ``*.profile.json`` inside the profile_folder and generate a dictionary 3 | {'resource.path': set(possible reference types)}. 4 | 5 | For example, since the valid referenced resources for the *definition* attribute of 6 | a *ReferralRequest* resource can be of type *ActivityDefinition* or *PlanDefinition*, 7 | the generated dictionary would contain the following entry: 8 | `{'ReferralRequest.definition': {'ActivityDefinition', 'PlanDefinition'}, ...}` 9 | """ 10 | 11 | from pathlib import Path 12 | import json 13 | import sys 14 | 15 | # Relative or absolute path to a directory that contains resource profile files 16 | profile_folder = "tools/fhir_parser/downloads" 17 | 18 | 19 | def generate(files=profile_folder): 20 | result = {} 21 | files = Path(files).glob("*.profile.json") 22 | for file in files: 23 | with open(file, "r") as f: 24 | # Parse json 25 | resource = json.loads(f.read()) 26 | # Example of great code 27 | elements = resource["snapshot"]["element"] 28 | for elem in elements: 29 | if "type" not in elem: 30 | continue 31 | types = elem["type"] 32 | for t in types: 33 | if "code" not in t or "targetProfile" not in t: 34 | continue 35 | if t["code"] == "Reference": 36 | if f'{elem["path"]}' not in result: 37 | result[f'{elem["path"]}'] = set() 38 | for prof in t["targetProfile"]: 39 | result[f'{elem["path"]}'].add(prof.split("/")[-1]) 40 | return result 41 | 42 | 43 | if "__main__" == __name__: 44 | if len(sys.argv) > 1 and Path(sys.argv[1]).is_dir(): 45 | reftypes = generate(sys.argv[1]) 46 | else: 47 | reftypes = generate() 48 | 49 | print(reftypes) 50 | -------------------------------------------------------------------------------- /fhirbug/Fhir/Resources/coding.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Generated from FHIR 4.0.0-a53ec6ee1b (http://hl7.org/fhir/StructureDefinition/Coding) on 2019-01-25. 5 | # 2019, SMART Health IT. 6 | ## 7 | 8 | 9 | from . import element 10 | 11 | class Coding(element.Element): 12 | """ A reference to a code defined by a terminology system. 13 | """ 14 | 15 | resource_type = "Coding" 16 | 17 | def __init__(self, jsondict=None, strict=True, **kwargs): 18 | """ Initialize all valid properties. 19 | 20 | :raises: FHIRValidationError on validation errors, unless strict is False 21 | :param dict jsondict: A JSON dictionary to use for initialization 22 | :param bool strict: If True (the default), invalid variables will raise a TypeError 23 | """ 24 | 25 | self.code = None 26 | """ Symbol in syntax defined by the system. 27 | Type `str`. """ 28 | 29 | self.display = None 30 | """ Representation defined by the system. 31 | Type `str`. """ 32 | 33 | self.system = None 34 | """ Identity of the terminology system. 35 | Type `str`. """ 36 | 37 | self.userSelected = None 38 | """ If this coding was chosen directly by the user. 39 | Type `bool`. """ 40 | 41 | self.version = None 42 | """ Version of the system - if relevant. 43 | Type `str`. """ 44 | 45 | super(Coding, self).__init__(jsondict=jsondict, strict=strict, **kwargs) 46 | 47 | def elementProperties(self): 48 | js = super(Coding, self).elementProperties() 49 | js.extend([ 50 | ("code", "code", str, False, None, False), 51 | ("display", "display", str, False, None, False), 52 | ("system", "system", str, False, None, False), 53 | ("userSelected", "userSelected", bool, False, None, False), 54 | ("version", "version", str, False, None, False), 55 | ]) 56 | return js 57 | 58 | -------------------------------------------------------------------------------- /fhirbug/Fhir/base/fhirsearch_tests.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | from models.fhirsearch import FHIRSearch 5 | 6 | if '__main__' == __name__: 7 | from models.patient import Patient 8 | print('1 '+FHIRSearch(Patient, {'name': 'Willis'}).construct()) 9 | print('1 '+Patient.where({'name': 'Willis'}).construct()) 10 | # print('1 '+Patient.where().name('Willis').construct()) 11 | print('= Patient?name=Willis') 12 | print('') 13 | print('2 '+FHIRSearch(Patient, {'name': {'$exact': 'Willis'}}).construct()) 14 | print('= Patient?name:exact=Willis') 15 | print('') 16 | print('3 '+FHIRSearch(Patient, {'name': {'$or': ['Willis', 'Wayne', 'Bruce']}}).construct()) 17 | print('= Patient?name=Willis,Wayne,Bruce') 18 | print('') 19 | print('4 '+FHIRSearch(Patient, {'name': {'$and': ['Willis', {'$exact': 'Bruce'}]}}).construct()) 20 | print('= Patient?name=Willis&name:exact=Bruce') 21 | print('') 22 | print('5 '+FHIRSearch(Patient, {'birthDate': {'$gt': '1950', '$lte': '1970'}}).construct()) 23 | print('= Patient?birthDate=>1950&birthDate=<=1970') 24 | print('') 25 | print('6 '+FHIRSearch(Patient, {'subject.name': {'$exact': 'Willis'}}).construct()) 26 | print('= Patient?subject.name:exact=Willis') 27 | print('') 28 | srch = FHIRSearch(Patient, {'subject': {'$type': 'Patient', 'name': 'Willis', 'birthDate': {'$gt': '1950', '$lte': '1970'}}}) 29 | print('7 '+srch.construct()) 30 | srch = Patient.where({'subject': {'$type': 'Patient', 'name': 'Willis', 'birthDate': {'$gt': '1950', '$lte': '1970'}}}) 31 | print('7 '+srch.construct()) 32 | print('= Patient?subject:Patient.name=Willis&subject:Patient.birthDate=>1950&subject:Patient.birthDate=<=1970') 33 | print('') 34 | print('8 '+FHIRSearch(Patient, {"name": {"$and": ["Willis", {"$exact": "Bruce"}]}, "birthDay": {"$and": [{"$lt": "1970", "$gte": "1950"}]}}).construct()) 35 | print('= Patient?name=Willis&name:exact=Bruce&birthDay=>=1950&birthDay=<1970') 36 | -------------------------------------------------------------------------------- /fhirbug/Fhir/base/settings.py: -------------------------------------------------------------------------------- 1 | # These are settings for the FHIR class generator. 2 | # All paths are relative to the `fhir-parser` directory. You may want to use 3 | # os.path.join() if the generator should work on Windows, too. 4 | 5 | from Default.settings import * 6 | 7 | BASE_DIR = '../../fhirbug/Fhir/base' 8 | TARGET_DIR = '../../fhirbug/Fhir/Resources' 9 | # Base URL for where to load specification data from 10 | specification_url = 'http://hl7.org/fhir/R4' 11 | 12 | # In which directory to find the templates. See below for settings that start with `tpl_`: these are the template names. 13 | tpl_base = BASE_DIR 14 | 15 | # classes/resources 16 | write_resources = True 17 | tpl_resource_target = TARGET_DIR # target directory to write the generated class files to 18 | tpl_codesystems_source = None # the template to use as source when writing enums for CodeSystems; can be `None` 19 | 20 | # factory methods 21 | write_factory = False 22 | tpl_factory_target = '../fhirclient/models/fhirelementfactory.py' # where to write the generated factory to 23 | 24 | # unit tests 25 | write_unittests = False 26 | tpl_unittest_target = '../fhirclient/models' # target directory to write the generated unit test files to 27 | 28 | 29 | # all these files should be copied to dirname(`tpl_resource_target_ptrn`): tuples of (path/to/file, module, array-of-class-names) 30 | manual_profiles = [ 31 | (BASE_DIR + '/fhirabstractbase.py', 'fhirabstractbase', [ 32 | 'boolean', 33 | 'string', 'base64Binary', 'code', 'id', 34 | 'decimal', 'integer', 'unsignedInt', 'positiveInt', 35 | 'uri', 'oid', 'uuid', 36 | 'FHIRAbstractBase', 37 | ]), 38 | (BASE_DIR + '/fhirabstractresource.py', 'fhirabstractresource', ['FHIRAbstractResource']), 39 | (BASE_DIR + '/fhirreference.py', 'fhirreference', ['FHIRReference']), 40 | (BASE_DIR + '/fhirdate.py', 'fhirdate', ['date', 'dateTime', 'instant', 'time']), 41 | (BASE_DIR + '/fhirsearch.py', 'fhirsearch', ['FHIRSearch']), 42 | ] 43 | -------------------------------------------------------------------------------- /fhirbug/Fhir/Resources/resource.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Generated from FHIR 4.0.0-a53ec6ee1b (http://hl7.org/fhir/StructureDefinition/Resource) on 2019-01-25. 5 | # 2019, SMART Health IT. 6 | ## 7 | 8 | 9 | from . import fhirabstractresource 10 | 11 | class Resource(fhirabstractresource.FHIRAbstractResource): 12 | """ Base Resource. 13 | 14 | This is the base resource type for everything. 15 | """ 16 | 17 | resource_type = "Resource" 18 | 19 | def __init__(self, jsondict=None, strict=True, **kwargs): 20 | """ Initialize all valid properties. 21 | 22 | :raises: FHIRValidationError on validation errors, unless strict is False 23 | :param dict jsondict: A JSON dictionary to use for initialization 24 | :param bool strict: If True (the default), invalid variables will raise a TypeError 25 | """ 26 | 27 | self.id = None 28 | """ Logical id of this artifact. 29 | Type `str`. """ 30 | 31 | self.implicitRules = None 32 | """ A set of rules under which this content was created. 33 | Type `str`. """ 34 | 35 | self.language = None 36 | """ Language of the resource content. 37 | Type `str`. """ 38 | 39 | self.meta = None 40 | """ Metadata about the resource. 41 | Type `Meta` (represented as `dict` in JSON). """ 42 | 43 | super(Resource, self).__init__(jsondict=jsondict, strict=strict, **kwargs) 44 | 45 | def elementProperties(self): 46 | js = super(Resource, self).elementProperties() 47 | js.extend([ 48 | ("id", "id", str, False, None, False), 49 | ("implicitRules", "implicitRules", str, False, None, False), 50 | ("language", "language", str, False, None, False), 51 | ("meta", "meta", meta.Meta, False, None, False), 52 | ]) 53 | return js 54 | 55 | 56 | import sys 57 | try: 58 | from . import meta 59 | except ImportError: 60 | meta = sys.modules[__package__ + '.meta'] -------------------------------------------------------------------------------- /fhirbug/Fhir/Resources/reference.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Generated from FHIR 4.0.0-a53ec6ee1b (http://hl7.org/fhir/StructureDefinition/Reference) on 2019-01-25. 5 | # 2019, SMART Health IT. 6 | ## 7 | 8 | 9 | from . import element 10 | 11 | class Reference(element.Element): 12 | """ A reference from one resource to another. 13 | """ 14 | 15 | resource_type = "Reference" 16 | 17 | def __init__(self, jsondict=None, strict=True, **kwargs): 18 | """ Initialize all valid properties. 19 | 20 | :raises: FHIRValidationError on validation errors, unless strict is False 21 | :param dict jsondict: A JSON dictionary to use for initialization 22 | :param bool strict: If True (the default), invalid variables will raise a TypeError 23 | """ 24 | 25 | self.display = None 26 | """ Text alternative for the resource. 27 | Type `str`. """ 28 | 29 | self.identifier = None 30 | """ Logical reference, when literal reference is not known. 31 | Type `Identifier` (represented as `dict` in JSON). """ 32 | 33 | self.reference = None 34 | """ Literal reference, Relative, internal or absolute URL. 35 | Type `str`. """ 36 | 37 | self.type = None 38 | """ Type the reference refers to (e.g. "Patient"). 39 | Type `str`. """ 40 | 41 | super(Reference, self).__init__(jsondict=jsondict, strict=strict, **kwargs) 42 | 43 | def elementProperties(self): 44 | js = super(Reference, self).elementProperties() 45 | js.extend([ 46 | ("display", "display", str, False, None, False), 47 | ("identifier", "identifier", identifier.Identifier, False, None, False), 48 | ("reference", "reference", str, False, None, False), 49 | ("type", "type", str, False, None, False), 50 | ]) 51 | return js 52 | 53 | 54 | import sys 55 | try: 56 | from . import identifier 57 | except ImportError: 58 | identifier = sys.modules[__package__ + '.identifier'] -------------------------------------------------------------------------------- /fhirbug/Fhir/Resources/binary.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Generated from FHIR 4.0.0-a53ec6ee1b (http://hl7.org/fhir/StructureDefinition/Binary) on 2019-01-25. 5 | # 2019, SMART Health IT. 6 | ## 7 | 8 | 9 | from . import resource 10 | 11 | class Binary(resource.Resource): 12 | """ Pure binary content defined by a format other than FHIR. 13 | 14 | A resource that represents the data of a single raw artifact as digital 15 | content accessible in its native format. A Binary resource can contain any 16 | content, whether text, image, pdf, zip archive, etc. 17 | """ 18 | 19 | resource_type = "Binary" 20 | 21 | def __init__(self, jsondict=None, strict=True, **kwargs): 22 | """ Initialize all valid properties. 23 | 24 | :raises: FHIRValidationError on validation errors, unless strict is False 25 | :param dict jsondict: A JSON dictionary to use for initialization 26 | :param bool strict: If True (the default), invalid variables will raise a TypeError 27 | """ 28 | 29 | self.contentType = None 30 | """ MimeType of the binary content. 31 | Type `str`. """ 32 | 33 | self.data = None 34 | """ The actual content. 35 | Type `str`. """ 36 | 37 | self.securityContext = None 38 | """ Identifies another resource to use as proxy when enforcing access 39 | control. 40 | Type `FHIRReference` (represented as `dict` in JSON). """ 41 | 42 | super(Binary, self).__init__(jsondict=jsondict, strict=strict, **kwargs) 43 | 44 | def elementProperties(self): 45 | js = super(Binary, self).elementProperties() 46 | js.extend([ 47 | ("contentType", "contentType", str, False, None, True), 48 | ("data", "data", str, False, None, False), 49 | ("securityContext", "securityContext", fhirreference.FHIRReference, False, None, False), 50 | ]) 51 | return js 52 | 53 | 54 | import sys 55 | try: 56 | from . import fhirreference 57 | except ImportError: 58 | fhirreference = sys.modules[__package__ + '.fhirreference'] -------------------------------------------------------------------------------- /fhirbug/Fhir/Resources/quantity.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Generated from FHIR 4.0.0-a53ec6ee1b (http://hl7.org/fhir/StructureDefinition/MoneyQuantity) on 2019-01-25. 5 | # 2019, SMART Health IT. 6 | ## 7 | 8 | 9 | from . import element 10 | 11 | class Quantity(element.Element): 12 | """ A measured or measurable amount. 13 | 14 | A measured amount (or an amount that can potentially be measured). Note 15 | that measured amounts include amounts that are not precisely quantified, 16 | including amounts involving arbitrary units and floating currencies. 17 | """ 18 | 19 | resource_type = "Quantity" 20 | 21 | def __init__(self, jsondict=None, strict=True, **kwargs): 22 | """ Initialize all valid properties. 23 | 24 | :raises: FHIRValidationError on validation errors, unless strict is False 25 | :param dict jsondict: A JSON dictionary to use for initialization 26 | :param bool strict: If True (the default), invalid variables will raise a TypeError 27 | """ 28 | 29 | self.code = None 30 | """ Coded form of the unit. 31 | Type `str`. """ 32 | 33 | self.comparator = None 34 | """ < | <= | >= | > - how to understand the value. 35 | Type `str`. """ 36 | 37 | self.system = None 38 | """ System that defines coded unit form. 39 | Type `str`. """ 40 | 41 | self.unit = None 42 | """ Unit representation. 43 | Type `str`. """ 44 | 45 | self.value = None 46 | """ Numerical value (with implicit precision). 47 | Type `float`. """ 48 | 49 | super(Quantity, self).__init__(jsondict=jsondict, strict=strict, **kwargs) 50 | 51 | def elementProperties(self): 52 | js = super(Quantity, self).elementProperties() 53 | js.extend([ 54 | ("code", "code", str, False, None, False), 55 | ("comparator", "comparator", str, False, None, False), 56 | ("system", "system", str, False, None, False), 57 | ("unit", "unit", str, False, None, False), 58 | ("value", "value", float, False, None, False), 59 | ]) 60 | return js 61 | 62 | -------------------------------------------------------------------------------- /fhirbug/utils.py: -------------------------------------------------------------------------------- 1 | import isodate 2 | import calendar 3 | from datetime import datetime 4 | from fhirbug.exceptions import QueryValidationError 5 | 6 | 7 | def transform_date(value, trim=True, to_datetime=False): 8 | """ Receive an date search string, trim the first to letters if needed 9 | (for example for a serach like ``date=le1990``) and return a date or datetime 10 | instance 11 | 12 | :param str value: date search string [xx]YYYY[-MM[-DD[Thh[:mm[:ss]]]]], where xx is a search modifiler (lt, gt, ne, ...) 13 | :param bool trim: Wether to trim the first two digits of the string 14 | """ 15 | if trim: 16 | value = value[2:] 17 | try: 18 | value = isodate.parse_datetime(value) 19 | return value 20 | except: 21 | try: 22 | value = isodate.parse_date(value) 23 | return ( 24 | datetime.combine(value, datetime.min.time()) if to_datetime else value 25 | ) 26 | except: 27 | raise QueryValidationError(f"{value} is not a valid ISO date") 28 | 29 | 30 | def date_ceil(value, trim=True): 31 | """ Receive a date search string and return a ceiling value for period-based 32 | date searches. 33 | """ 34 | length = len(value) 35 | if trim: 36 | length -= 2 37 | 38 | value = transform_date(value, trim) 39 | 40 | if length == 4: 41 | return datetime(value.year, 12, 31, 23, 59, 59, 59) 42 | elif length == 7: 43 | first, last = calendar.monthrange(value.year, value.month) 44 | return datetime(value.year, value.month, last, 23, 59, 59, 59) 45 | elif length == 10: 46 | return datetime(value.year, value.month, value.day, 23, 59, 59, 59) 47 | elif length == 13: 48 | return datetime(value.year, value.month, value.day, value.hour, 59, 59, 59) 49 | elif length == 16: 50 | return datetime( 51 | value.year, value.month, value.day, value.hour, value.minute, 59, 59 52 | ) 53 | elif length == 19: 54 | return datetime( 55 | value.year, 56 | value.month, 57 | value.day, 58 | value.hour, 59 | value.minute, 60 | value.second, 61 | 59, 62 | ) 63 | else: 64 | return value 65 | -------------------------------------------------------------------------------- /fhirbug/db/backends/SQLAlchemy/models.py: -------------------------------------------------------------------------------- 1 | """ 2 | SQLAlchemy backend. 3 | ================== 4 | 5 | A declarative base class must be provided via the 'BASE_CLASS' setting. 6 | All models inherit from this class. 7 | Provides AbstractBaseModel as an abstract base for resource mappings to 8 | inherit from. 9 | 10 | Settings: 11 | 12 | SQLALCHEMY_CONFIG = { 13 | 'URI': # The connection string for xc_Oracle 14 | 'BASE_CLASS': # A string containing the module path to a declarative base class. 15 | } 16 | 17 | 18 | """ 19 | 20 | 21 | from fhirbug.db.backends.SQLAlchemy.pagination import paginate 22 | from fhirbug.db.backends.SQLAlchemy.base import Base, session 23 | 24 | from fhirbug.models.mixins import FhirAbstractBaseMixin, FhirBaseModelMixin 25 | from fhirbug.exceptions import DoesNotExistError 26 | 27 | 28 | class AbstractBaseModel(Base, FhirAbstractBaseMixin): 29 | """ 30 | The base class to provide functionality to 31 | our models. 32 | """ 33 | 34 | __abstract__ = True 35 | 36 | @classmethod 37 | def _get_orm_query(cls): 38 | return cls.query 39 | 40 | @classmethod 41 | def _get_item_from_pk(cls, pk): 42 | item = cls.query.get(pk) 43 | if item is None: 44 | raise DoesNotExistError(pk, cls.__name__) 45 | return item 46 | 47 | @classmethod 48 | def _delete_item(cls, item): 49 | session.delete(item) 50 | try: 51 | session.commit() 52 | except Exception as e: 53 | session.rollback() 54 | raise e 55 | 56 | 57 | class FhirBaseModel(AbstractBaseModel, FhirBaseModelMixin): 58 | __abstract__ = True 59 | 60 | @classmethod 61 | def _after_create(cls, instance): 62 | session.add(instance) 63 | try: 64 | session.commit() 65 | except Exception as e: 66 | session.rollback() 67 | raise e 68 | return instance 69 | 70 | @classmethod 71 | def _after_update(cls, instance): 72 | try: 73 | session.commit() 74 | except Exception as e: 75 | session.rollback() 76 | raise e 77 | return instance 78 | 79 | @classmethod 80 | def paginate(cls, *args, **kwargs): 81 | return paginate(*args, **kwargs) 82 | -------------------------------------------------------------------------------- /fhirbug/Fhir/Resources/expression.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Generated from FHIR 4.0.0-a53ec6ee1b (http://hl7.org/fhir/StructureDefinition/Expression) on 2019-01-25. 5 | # 2019, SMART Health IT. 6 | ## 7 | 8 | 9 | from . import element 10 | 11 | class Expression(element.Element): 12 | """ An expression that can be used to generate a value. 13 | 14 | A expression that is evaluated in a specified context and returns a value. 15 | The context of use of the expression must specify the context in which the 16 | expression is evaluated, and how the result of the expression is used. 17 | """ 18 | 19 | resource_type = "Expression" 20 | 21 | def __init__(self, jsondict=None, strict=True, **kwargs): 22 | """ Initialize all valid properties. 23 | 24 | :raises: FHIRValidationError on validation errors, unless strict is False 25 | :param dict jsondict: A JSON dictionary to use for initialization 26 | :param bool strict: If True (the default), invalid variables will raise a TypeError 27 | """ 28 | 29 | self.description = None 30 | """ Natural language description of the condition. 31 | Type `str`. """ 32 | 33 | self.expression = None 34 | """ Expression in specified language. 35 | Type `str`. """ 36 | 37 | self.language = None 38 | """ text/cql | text/fhirpath | application/x-fhir-query | etc.. 39 | Type `str`. """ 40 | 41 | self.name = None 42 | """ Short name assigned to expression for reuse. 43 | Type `str`. """ 44 | 45 | self.reference = None 46 | """ Where the expression is found. 47 | Type `str`. """ 48 | 49 | super(Expression, self).__init__(jsondict=jsondict, strict=strict, **kwargs) 50 | 51 | def elementProperties(self): 52 | js = super(Expression, self).elementProperties() 53 | js.extend([ 54 | ("description", "description", str, False, None, False), 55 | ("expression", "expression", str, False, None, False), 56 | ("language", "language", str, False, None, True), 57 | ("name", "name", str, False, None, False), 58 | ("reference", "reference", str, False, None, False), 59 | ]) 60 | return js 61 | 62 | -------------------------------------------------------------------------------- /fhirbug/Fhir/Resources/annotation.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Generated from FHIR 4.0.0-a53ec6ee1b (http://hl7.org/fhir/StructureDefinition/Annotation) on 2019-01-25. 5 | # 2019, SMART Health IT. 6 | ## 7 | 8 | 9 | from . import element 10 | 11 | class Annotation(element.Element): 12 | """ Text node with attribution. 13 | 14 | A text note which also contains information about who made the statement 15 | and when. 16 | """ 17 | 18 | resource_type = "Annotation" 19 | 20 | def __init__(self, jsondict=None, strict=True, **kwargs): 21 | """ Initialize all valid properties. 22 | 23 | :raises: FHIRValidationError on validation errors, unless strict is False 24 | :param dict jsondict: A JSON dictionary to use for initialization 25 | :param bool strict: If True (the default), invalid variables will raise a TypeError 26 | """ 27 | 28 | self.authorReference = None 29 | """ Individual responsible for the annotation. 30 | Type `FHIRReference` (represented as `dict` in JSON). """ 31 | 32 | self.authorString = None 33 | """ Individual responsible for the annotation. 34 | Type `str`. """ 35 | 36 | self.text = None 37 | """ The annotation - text content (as markdown). 38 | Type `str`. """ 39 | 40 | self.time = None 41 | """ When the annotation was made. 42 | Type `FHIRDate` (represented as `str` in JSON). """ 43 | 44 | super(Annotation, self).__init__(jsondict=jsondict, strict=strict, **kwargs) 45 | 46 | def elementProperties(self): 47 | js = super(Annotation, self).elementProperties() 48 | js.extend([ 49 | ("authorReference", "authorReference", fhirreference.FHIRReference, False, "author", False), 50 | ("authorString", "authorString", str, False, "author", False), 51 | ("text", "text", str, False, None, True), 52 | ("time", "time", fhirdate.FHIRDate, False, None, False), 53 | ]) 54 | return js 55 | 56 | 57 | import sys 58 | try: 59 | from . import fhirdate 60 | except ImportError: 61 | fhirdate = sys.modules[__package__ + '.fhirdate'] 62 | try: 63 | from . import fhirreference 64 | except ImportError: 65 | fhirreference = sys.modules[__package__ + '.fhirreference'] -------------------------------------------------------------------------------- /fhirbug/Fhir/Resources/contactpoint.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Generated from FHIR 4.0.0-a53ec6ee1b (http://hl7.org/fhir/StructureDefinition/ContactPoint) on 2019-01-25. 5 | # 2019, SMART Health IT. 6 | ## 7 | 8 | 9 | from . import element 10 | 11 | class ContactPoint(element.Element): 12 | """ Details of a Technology mediated contact point (phone, fax, email, etc.). 13 | 14 | Details for all kinds of technology mediated contact points for a person or 15 | organization, including telephone, email, etc. 16 | """ 17 | 18 | resource_type = "ContactPoint" 19 | 20 | def __init__(self, jsondict=None, strict=True, **kwargs): 21 | """ Initialize all valid properties. 22 | 23 | :raises: FHIRValidationError on validation errors, unless strict is False 24 | :param dict jsondict: A JSON dictionary to use for initialization 25 | :param bool strict: If True (the default), invalid variables will raise a TypeError 26 | """ 27 | 28 | self.period = None 29 | """ Time period when the contact point was/is in use. 30 | Type `Period` (represented as `dict` in JSON). """ 31 | 32 | self.rank = None 33 | """ Specify preferred order of use (1 = highest). 34 | Type `int`. """ 35 | 36 | self.system = None 37 | """ phone | fax | email | pager | url | sms | other. 38 | Type `str`. """ 39 | 40 | self.use = None 41 | """ home | work | temp | old | mobile - purpose of this contact point. 42 | Type `str`. """ 43 | 44 | self.value = None 45 | """ The actual contact point details. 46 | Type `str`. """ 47 | 48 | super(ContactPoint, self).__init__(jsondict=jsondict, strict=strict, **kwargs) 49 | 50 | def elementProperties(self): 51 | js = super(ContactPoint, self).elementProperties() 52 | js.extend([ 53 | ("period", "period", period.Period, False, None, False), 54 | ("rank", "rank", int, False, None, False), 55 | ("system", "system", str, False, None, False), 56 | ("use", "use", str, False, None, False), 57 | ("value", "value", str, False, None, False), 58 | ]) 59 | return js 60 | 61 | 62 | import sys 63 | try: 64 | from . import period 65 | except ImportError: 66 | period = sys.modules[__package__ + '.period'] -------------------------------------------------------------------------------- /fhirbug/Fhir/Resources/domainresource.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Generated from FHIR 4.0.0-a53ec6ee1b (http://hl7.org/fhir/StructureDefinition/DomainResource) on 2019-01-25. 5 | # 2019, SMART Health IT. 6 | ## 7 | 8 | 9 | from . import resource 10 | 11 | class DomainResource(resource.Resource): 12 | """ A resource with narrative, extensions, and contained resources. 13 | 14 | A resource that includes narrative, extensions, and contained resources. 15 | """ 16 | 17 | resource_type = "DomainResource" 18 | 19 | def __init__(self, jsondict=None, strict=True, **kwargs): 20 | """ Initialize all valid properties. 21 | 22 | :raises: FHIRValidationError on validation errors, unless strict is False 23 | :param dict jsondict: A JSON dictionary to use for initialization 24 | :param bool strict: If True (the default), invalid variables will raise a TypeError 25 | """ 26 | 27 | self.contained = None 28 | """ Contained, inline Resources. 29 | List of `Resource` items (represented as `dict` in JSON). """ 30 | 31 | self.extension = None 32 | """ Additional content defined by implementations. 33 | List of `Extension` items (represented as `dict` in JSON). """ 34 | 35 | self.modifierExtension = None 36 | """ Extensions that cannot be ignored. 37 | List of `Extension` items (represented as `dict` in JSON). """ 38 | 39 | self.text = None 40 | """ Text summary of the resource, for human interpretation. 41 | Type `Narrative` (represented as `dict` in JSON). """ 42 | 43 | super(DomainResource, self).__init__(jsondict=jsondict, strict=strict, **kwargs) 44 | 45 | def elementProperties(self): 46 | js = super(DomainResource, self).elementProperties() 47 | js.extend([ 48 | ("contained", "contained", resource.Resource, True, None, False), 49 | ("extension", "extension", extension.Extension, True, None, False), 50 | ("modifierExtension", "modifierExtension", extension.Extension, True, None, False), 51 | ("text", "text", narrative.Narrative, False, None, False), 52 | ]) 53 | return js 54 | 55 | 56 | import sys 57 | try: 58 | from . import extension 59 | except ImportError: 60 | extension = sys.modules[__package__ + '.extension'] 61 | try: 62 | from . import narrative 63 | except ImportError: 64 | narrative = sys.modules[__package__ + '.narrative'] -------------------------------------------------------------------------------- /fhirbug/Fhir/base/template-unittest.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Generated from FHIR {{ info.version }} on {{ info.date }}. 5 | # {{ info.year }}, SMART Health IT. 6 | 7 | 8 | import os 9 | import io 10 | import unittest 11 | import json 12 | from . import {{ class.module }} 13 | from .fhirdate import FHIRDate 14 | 15 | 16 | class {{ class.name }}Tests(unittest.TestCase): 17 | def instantiate_from(self, filename): 18 | datadir = os.environ.get('FHIR_UNITTEST_DATADIR') or '' 19 | with io.open(os.path.join(datadir, filename), 'r', encoding='utf-8') as handle: 20 | js = json.load(handle) 21 | self.assertEqual("{{ class.name }}", js["resourceType"]) 22 | return {{ class.module }}.{{ class.name }}(js) 23 | 24 | {%- for tcase in tests %} 25 | 26 | def test{{ class.name }}{{ loop.index }}(self): 27 | inst = self.instantiate_from("{{ tcase.filename }}") 28 | self.assertIsNotNone(inst, "Must have instantiated a {{ class.name }} instance") 29 | self.impl{{ class.name }}{{ loop.index }}(inst) 30 | 31 | js = inst.as_json() 32 | self.assertEqual("{{ class.name }}", js["resourceType"]) 33 | inst2 = {{ class.module }}.{{ class.name }}(js) 34 | self.impl{{ class.name }}{{ loop.index }}(inst2) 35 | 36 | def impl{{ class.name }}{{ loop.index }}(self, inst): 37 | {%- for onetest in tcase.tests %} 38 | {%- if "str" == onetest.klass.name %} 39 | self.assertEqual(inst.{{ onetest.path }}, "{{ onetest.value|replace('"', '\\"') }}") 40 | {%- else %}{% if "int" == onetest.klass.name or "float" == onetest.klass.name or "NSDecimalNumber" == onetest.klass.name %} 41 | self.assertEqual(inst.{{ onetest.path }}, {{ onetest.value }}) 42 | {%- else %}{% if "bool" == onetest.klass.name %} 43 | {%- if onetest.value %} 44 | self.assertTrue(inst.{{ onetest.path }}) 45 | {%- else %} 46 | self.assertFalse(inst.{{ onetest.path }}) 47 | {%- endif %} 48 | {%- else %}{% if "FHIRDate" == onetest.klass.name %} 49 | self.assertEqual(inst.{{ onetest.path }}.date, FHIRDate("{{ onetest.value }}").date) 50 | self.assertEqual(inst.{{ onetest.path }}.as_json(), "{{ onetest.value }}") 51 | {%- else %} 52 | # Don't know how to create unit test for "{{ onetest.path }}", which is a {{ onetest.klass.name }} 53 | {%- endif %}{% endif %}{% endif %}{% endif %} 54 | {%- endfor %} 55 | {%- endfor %} 56 | 57 | 58 | -------------------------------------------------------------------------------- /fhirbug/Fhir/Resources/parameterdefinition.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Generated from FHIR 4.0.0-a53ec6ee1b (http://hl7.org/fhir/StructureDefinition/ParameterDefinition) on 2019-01-25. 5 | # 2019, SMART Health IT. 6 | ## 7 | 8 | 9 | from . import element 10 | 11 | class ParameterDefinition(element.Element): 12 | """ Definition of a parameter to a module. 13 | 14 | The parameters to the module. This collection specifies both the input and 15 | output parameters. Input parameters are provided by the caller as part of 16 | the $evaluate operation. Output parameters are included in the 17 | GuidanceResponse. 18 | """ 19 | 20 | resource_type = "ParameterDefinition" 21 | 22 | def __init__(self, jsondict=None, strict=True, **kwargs): 23 | """ Initialize all valid properties. 24 | 25 | :raises: FHIRValidationError on validation errors, unless strict is False 26 | :param dict jsondict: A JSON dictionary to use for initialization 27 | :param bool strict: If True (the default), invalid variables will raise a TypeError 28 | """ 29 | 30 | self.documentation = None 31 | """ A brief description of the parameter. 32 | Type `str`. """ 33 | 34 | self.max = None 35 | """ Maximum cardinality (a number of *). 36 | Type `str`. """ 37 | 38 | self.min = None 39 | """ Minimum cardinality. 40 | Type `int`. """ 41 | 42 | self.name = None 43 | """ Name used to access the parameter value. 44 | Type `str`. """ 45 | 46 | self.profile = None 47 | """ What profile the value is expected to be. 48 | Type `str`. """ 49 | 50 | self.type = None 51 | """ What type of value. 52 | Type `str`. """ 53 | 54 | self.use = None 55 | """ in | out. 56 | Type `str`. """ 57 | 58 | super(ParameterDefinition, self).__init__(jsondict=jsondict, strict=strict, **kwargs) 59 | 60 | def elementProperties(self): 61 | js = super(ParameterDefinition, self).elementProperties() 62 | js.extend([ 63 | ("documentation", "documentation", str, False, None, False), 64 | ("max", "max", str, False, None, False), 65 | ("min", "min", int, False, None, False), 66 | ("name", "name", str, False, None, False), 67 | ("profile", "profile", str, False, None, False), 68 | ("type", "type", str, False, None, True), 69 | ("use", "use", str, False, None, True), 70 | ]) 71 | return js 72 | 73 | -------------------------------------------------------------------------------- /fhirbug/Fhir/Resources/humanname.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Generated from FHIR 4.0.0-a53ec6ee1b (http://hl7.org/fhir/StructureDefinition/HumanName) on 2019-01-25. 5 | # 2019, SMART Health IT. 6 | ## 7 | 8 | 9 | from . import element 10 | 11 | class HumanName(element.Element): 12 | """ Name of a human - parts and usage. 13 | 14 | A human's name with the ability to identify parts and usage. 15 | """ 16 | 17 | resource_type = "HumanName" 18 | 19 | def __init__(self, jsondict=None, strict=True, **kwargs): 20 | """ Initialize all valid properties. 21 | 22 | :raises: FHIRValidationError on validation errors, unless strict is False 23 | :param dict jsondict: A JSON dictionary to use for initialization 24 | :param bool strict: If True (the default), invalid variables will raise a TypeError 25 | """ 26 | 27 | self.family = None 28 | """ Family name (often called 'Surname'). 29 | Type `str`. """ 30 | 31 | self.given = None 32 | """ Given names (not always 'first'). Includes middle names. 33 | List of `str` items. """ 34 | 35 | self.period = None 36 | """ Time period when name was/is in use. 37 | Type `Period` (represented as `dict` in JSON). """ 38 | 39 | self.prefix = None 40 | """ Parts that come before the name. 41 | List of `str` items. """ 42 | 43 | self.suffix = None 44 | """ Parts that come after the name. 45 | List of `str` items. """ 46 | 47 | self.text = None 48 | """ Text representation of the full name. 49 | Type `str`. """ 50 | 51 | self.use = None 52 | """ usual | official | temp | nickname | anonymous | old | maiden. 53 | Type `str`. """ 54 | 55 | super(HumanName, self).__init__(jsondict=jsondict, strict=strict, **kwargs) 56 | 57 | def elementProperties(self): 58 | js = super(HumanName, self).elementProperties() 59 | js.extend([ 60 | ("family", "family", str, False, None, False), 61 | ("given", "given", str, True, None, False), 62 | ("period", "period", period.Period, False, None, False), 63 | ("prefix", "prefix", str, True, None, False), 64 | ("suffix", "suffix", str, True, None, False), 65 | ("text", "text", str, False, None, False), 66 | ("use", "use", str, False, None, False), 67 | ]) 68 | return js 69 | 70 | 71 | import sys 72 | try: 73 | from . import period 74 | except ImportError: 75 | period = sys.modules[__package__ + '.period'] -------------------------------------------------------------------------------- /fhirbug/Fhir/Resources/sampleddata.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Generated from FHIR 4.0.0-a53ec6ee1b (http://hl7.org/fhir/StructureDefinition/SampledData) on 2019-01-25. 5 | # 2019, SMART Health IT. 6 | ## 7 | 8 | 9 | from . import element 10 | 11 | class SampledData(element.Element): 12 | """ A series of measurements taken by a device. 13 | 14 | A series of measurements taken by a device, with upper and lower limits. 15 | There may be more than one dimension in the data. 16 | """ 17 | 18 | resource_type = "SampledData" 19 | 20 | def __init__(self, jsondict=None, strict=True, **kwargs): 21 | """ Initialize all valid properties. 22 | 23 | :raises: FHIRValidationError on validation errors, unless strict is False 24 | :param dict jsondict: A JSON dictionary to use for initialization 25 | :param bool strict: If True (the default), invalid variables will raise a TypeError 26 | """ 27 | 28 | self.data = None 29 | """ Decimal values with spaces, or "E" | "U" | "L". 30 | Type `str`. """ 31 | 32 | self.dimensions = None 33 | """ Number of sample points at each time point. 34 | Type `int`. """ 35 | 36 | self.factor = None 37 | """ Multiply data by this before adding to origin. 38 | Type `float`. """ 39 | 40 | self.lowerLimit = None 41 | """ Lower limit of detection. 42 | Type `float`. """ 43 | 44 | self.origin = None 45 | """ Zero value and units. 46 | Type `Quantity` (represented as `dict` in JSON). """ 47 | 48 | self.period = None 49 | """ Number of milliseconds between samples. 50 | Type `float`. """ 51 | 52 | self.upperLimit = None 53 | """ Upper limit of detection. 54 | Type `float`. """ 55 | 56 | super(SampledData, self).__init__(jsondict=jsondict, strict=strict, **kwargs) 57 | 58 | def elementProperties(self): 59 | js = super(SampledData, self).elementProperties() 60 | js.extend([ 61 | ("data", "data", str, False, None, False), 62 | ("dimensions", "dimensions", int, False, None, True), 63 | ("factor", "factor", float, False, None, False), 64 | ("lowerLimit", "lowerLimit", float, False, None, False), 65 | ("origin", "origin", quantity.Quantity, False, None, True), 66 | ("period", "period", float, False, None, True), 67 | ("upperLimit", "upperLimit", float, False, None, False), 68 | ]) 69 | return js 70 | 71 | 72 | import sys 73 | try: 74 | from . import quantity 75 | except ImportError: 76 | quantity = sys.modules[__package__ + '.quantity'] -------------------------------------------------------------------------------- /fhirbug/Fhir/Resources/relatedartifact.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Generated from FHIR 4.0.0-a53ec6ee1b (http://hl7.org/fhir/StructureDefinition/RelatedArtifact) on 2019-01-25. 5 | # 2019, SMART Health IT. 6 | ## 7 | 8 | 9 | from . import element 10 | 11 | class RelatedArtifact(element.Element): 12 | """ Related artifacts for a knowledge resource. 13 | 14 | Related artifacts such as additional documentation, justification, or 15 | bibliographic references. 16 | """ 17 | 18 | resource_type = "RelatedArtifact" 19 | 20 | def __init__(self, jsondict=None, strict=True, **kwargs): 21 | """ Initialize all valid properties. 22 | 23 | :raises: FHIRValidationError on validation errors, unless strict is False 24 | :param dict jsondict: A JSON dictionary to use for initialization 25 | :param bool strict: If True (the default), invalid variables will raise a TypeError 26 | """ 27 | 28 | self.citation = None 29 | """ Bibliographic citation for the artifact. 30 | Type `str`. """ 31 | 32 | self.display = None 33 | """ Brief description of the related artifact. 34 | Type `str`. """ 35 | 36 | self.document = None 37 | """ What document is being referenced. 38 | Type `Attachment` (represented as `dict` in JSON). """ 39 | 40 | self.label = None 41 | """ Short label. 42 | Type `str`. """ 43 | 44 | self.resource = None 45 | """ What resource is being referenced. 46 | Type `str`. """ 47 | 48 | self.type = None 49 | """ documentation | justification | citation | predecessor | successor 50 | | derived-from | depends-on | composed-of. 51 | Type `str`. """ 52 | 53 | self.url = None 54 | """ Where the artifact can be accessed. 55 | Type `str`. """ 56 | 57 | super(RelatedArtifact, self).__init__(jsondict=jsondict, strict=strict, **kwargs) 58 | 59 | def elementProperties(self): 60 | js = super(RelatedArtifact, self).elementProperties() 61 | js.extend([ 62 | ("citation", "citation", str, False, None, False), 63 | ("display", "display", str, False, None, False), 64 | ("document", "document", attachment.Attachment, False, None, False), 65 | ("label", "label", str, False, None, False), 66 | ("resource", "resource", str, False, None, False), 67 | ("type", "type", str, False, None, True), 68 | ("url", "url", str, False, None, False), 69 | ]) 70 | return js 71 | 72 | 73 | import sys 74 | try: 75 | from . import attachment 76 | except ImportError: 77 | attachment = sys.modules[__package__ + '.attachment'] -------------------------------------------------------------------------------- /fhirbug/Fhir/Resources/attachment.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Generated from FHIR 4.0.0-a53ec6ee1b (http://hl7.org/fhir/StructureDefinition/Attachment) on 2019-01-25. 5 | # 2019, SMART Health IT. 6 | ## 7 | 8 | 9 | from . import element 10 | 11 | class Attachment(element.Element): 12 | """ Content in a format defined elsewhere. 13 | 14 | For referring to data content defined in other formats. 15 | """ 16 | 17 | resource_type = "Attachment" 18 | 19 | def __init__(self, jsondict=None, strict=True, **kwargs): 20 | """ Initialize all valid properties. 21 | 22 | :raises: FHIRValidationError on validation errors, unless strict is False 23 | :param dict jsondict: A JSON dictionary to use for initialization 24 | :param bool strict: If True (the default), invalid variables will raise a TypeError 25 | """ 26 | 27 | self.contentType = None 28 | """ Mime type of the content, with charset etc.. 29 | Type `str`. """ 30 | 31 | self.creation = None 32 | """ Date attachment was first created. 33 | Type `FHIRDate` (represented as `str` in JSON). """ 34 | 35 | self.data = None 36 | """ Data inline, base64ed. 37 | Type `str`. """ 38 | 39 | self.hash = None 40 | """ Hash of the data (sha-1, base64ed). 41 | Type `str`. """ 42 | 43 | self.language = None 44 | """ Human language of the content (BCP-47). 45 | Type `str`. """ 46 | 47 | self.size = None 48 | """ Number of bytes of content (if url provided). 49 | Type `int`. """ 50 | 51 | self.title = None 52 | """ Label to display in place of the data. 53 | Type `str`. """ 54 | 55 | self.url = None 56 | """ Uri where the data can be found. 57 | Type `str`. """ 58 | 59 | super(Attachment, self).__init__(jsondict=jsondict, strict=strict, **kwargs) 60 | 61 | def elementProperties(self): 62 | js = super(Attachment, self).elementProperties() 63 | js.extend([ 64 | ("contentType", "contentType", str, False, None, False), 65 | ("creation", "creation", fhirdate.FHIRDate, False, None, False), 66 | ("data", "data", str, False, None, False), 67 | ("hash", "hash", str, False, None, False), 68 | ("language", "language", str, False, None, False), 69 | ("size", "size", int, False, None, False), 70 | ("title", "title", str, False, None, False), 71 | ("url", "url", str, False, None, False), 72 | ]) 73 | return js 74 | 75 | 76 | import sys 77 | try: 78 | from . import fhirdate 79 | except ImportError: 80 | fhirdate = sys.modules[__package__ + '.fhirdate'] -------------------------------------------------------------------------------- /fhirbug/Fhir/Resources/meta.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Generated from FHIR 4.0.0-a53ec6ee1b (http://hl7.org/fhir/StructureDefinition/Meta) on 2019-01-25. 5 | # 2019, SMART Health IT. 6 | ## 7 | 8 | 9 | from . import element 10 | 11 | class Meta(element.Element): 12 | """ Metadata about a resource. 13 | 14 | The metadata about a resource. This is content in the resource that is 15 | maintained by the infrastructure. Changes to the content might not always 16 | be associated with version changes to the resource. 17 | """ 18 | 19 | resource_type = "Meta" 20 | 21 | def __init__(self, jsondict=None, strict=True, **kwargs): 22 | """ Initialize all valid properties. 23 | 24 | :raises: FHIRValidationError on validation errors, unless strict is False 25 | :param dict jsondict: A JSON dictionary to use for initialization 26 | :param bool strict: If True (the default), invalid variables will raise a TypeError 27 | """ 28 | 29 | self.lastUpdated = None 30 | """ When the resource version last changed. 31 | Type `FHIRDate` (represented as `str` in JSON). """ 32 | 33 | self.profile = None 34 | """ Profiles this resource claims to conform to. 35 | List of `str` items. """ 36 | 37 | self.security = None 38 | """ Security Labels applied to this resource. 39 | List of `Coding` items (represented as `dict` in JSON). """ 40 | 41 | self.source = None 42 | """ Identifies where the resource comes from. 43 | Type `str`. """ 44 | 45 | self.tag = None 46 | """ Tags applied to this resource. 47 | List of `Coding` items (represented as `dict` in JSON). """ 48 | 49 | self.versionId = None 50 | """ Version specific identifier. 51 | Type `str`. """ 52 | 53 | super(Meta, self).__init__(jsondict=jsondict, strict=strict, **kwargs) 54 | 55 | def elementProperties(self): 56 | js = super(Meta, self).elementProperties() 57 | js.extend([ 58 | ("lastUpdated", "lastUpdated", fhirdate.FHIRDate, False, None, False), 59 | ("profile", "profile", str, True, None, False), 60 | ("security", "security", coding.Coding, True, None, False), 61 | ("source", "source", str, False, None, False), 62 | ("tag", "tag", coding.Coding, True, None, False), 63 | ("versionId", "versionId", str, False, None, False), 64 | ]) 65 | return js 66 | 67 | 68 | import sys 69 | try: 70 | from . import coding 71 | except ImportError: 72 | coding = sys.modules[__package__ + '.coding'] 73 | try: 74 | from . import fhirdate 75 | except ImportError: 76 | fhirdate = sys.modules[__package__ + '.fhirdate'] -------------------------------------------------------------------------------- /fhirbug/exceptions.py: -------------------------------------------------------------------------------- 1 | class DoesNotExistError(Exception): 2 | """ 3 | A http request query was malformed or not understood by the server 4 | """ 5 | 6 | def __init__(self, pk=None, resource_type=None): 7 | self.pk = pk 8 | self.resource_type = resource_type 9 | 10 | 11 | class QueryValidationError(Exception): 12 | """ 13 | A http request query was malformed or not understood by the server 14 | """ 15 | 16 | pass 17 | 18 | 19 | class MappingValidationError(Exception): 20 | """ 21 | A fhir mapping has been set up wrong 22 | """ 23 | 24 | pass 25 | 26 | 27 | class ConfigurationError(Exception): 28 | """ 29 | Something is wrong with the settings 30 | """ 31 | 32 | pass 33 | 34 | 35 | class InvalidOperationError(Exception): 36 | """ 37 | The requested opertion is not valid 38 | """ 39 | 40 | pass 41 | 42 | 43 | class UnsupportedOperationError(Exception): 44 | """ 45 | The requested opertion is not supported by this server 46 | """ 47 | 48 | pass 49 | 50 | 51 | class MappingException(Exception): 52 | """ 53 | A fhir mapping received data that was not correct 54 | """ 55 | 56 | pass 57 | 58 | 59 | class OperationError(Exception): 60 | """ 61 | An exception that happens during a requested operation that 62 | should be returned as an OperationOutcome to the user. 63 | """ 64 | 65 | def __init__( 66 | self, severity="error", code="exception", diagnostics="", status_code=500 67 | ): 68 | self.severity = severity 69 | self.code = code 70 | self.diagnostics = diagnostics 71 | self.status_code = status_code 72 | 73 | def to_fhir(self): 74 | """ 75 | Express the exception as an OperationOutcome resource. 76 | This allows us to catch it and immediately return it to the user. 77 | """ 78 | from fhirbug.Fhir.resources import OperationOutcome 79 | 80 | return OperationOutcome( 81 | { 82 | "issue": [ 83 | { 84 | "severity": self.severity, 85 | "code": self.code, 86 | "diagnostics": self.diagnostics, 87 | } 88 | ] 89 | } 90 | ) 91 | 92 | 93 | class AuthorizationError(Exception): 94 | """ 95 | The request could not be authorized. 96 | """ 97 | 98 | def __init__(self, auditEvent, query=None): 99 | #: This exception carries an auditEvent resource describing why authorization failed 100 | #: It can be thrown anywhere in a mappings ``.get()`` method. 101 | self.auditEvent = auditEvent 102 | self.query = query 103 | -------------------------------------------------------------------------------- /fhirbug/Fhir/Resources/identifier.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Generated from FHIR 4.0.0-a53ec6ee1b (http://hl7.org/fhir/StructureDefinition/Identifier) on 2019-01-25. 5 | # 2019, SMART Health IT. 6 | ## 7 | 8 | 9 | from . import element 10 | 11 | class Identifier(element.Element): 12 | """ An identifier intended for computation. 13 | 14 | An identifier - identifies some entity uniquely and unambiguously. 15 | Typically this is used for business identifiers. 16 | """ 17 | 18 | resource_type = "Identifier" 19 | 20 | def __init__(self, jsondict=None, strict=True, **kwargs): 21 | """ Initialize all valid properties. 22 | 23 | :raises: FHIRValidationError on validation errors, unless strict is False 24 | :param dict jsondict: A JSON dictionary to use for initialization 25 | :param bool strict: If True (the default), invalid variables will raise a TypeError 26 | """ 27 | 28 | self.assigner = None 29 | """ Organization that issued id (may be just text). 30 | Type `FHIRReference` (represented as `dict` in JSON). """ 31 | 32 | self.period = None 33 | """ Time period when id is/was valid for use. 34 | Type `Period` (represented as `dict` in JSON). """ 35 | 36 | self.system = None 37 | """ The namespace for the identifier value. 38 | Type `str`. """ 39 | 40 | self.type = None 41 | """ Description of identifier. 42 | Type `CodeableConcept` (represented as `dict` in JSON). """ 43 | 44 | self.use = None 45 | """ usual | official | temp | secondary | old (If known). 46 | Type `str`. """ 47 | 48 | self.value = None 49 | """ The value that is unique. 50 | Type `str`. """ 51 | 52 | super(Identifier, self).__init__(jsondict=jsondict, strict=strict, **kwargs) 53 | 54 | def elementProperties(self): 55 | js = super(Identifier, self).elementProperties() 56 | js.extend([ 57 | ("assigner", "assigner", fhirreference.FHIRReference, False, None, False), 58 | ("period", "period", period.Period, False, None, False), 59 | ("system", "system", str, False, None, False), 60 | ("type", "type", codeableconcept.CodeableConcept, False, None, False), 61 | ("use", "use", str, False, None, False), 62 | ("value", "value", str, False, None, False), 63 | ]) 64 | return js 65 | 66 | 67 | import sys 68 | try: 69 | from . import codeableconcept 70 | except ImportError: 71 | codeableconcept = sys.modules[__package__ + '.codeableconcept'] 72 | try: 73 | from . import fhirreference 74 | except ImportError: 75 | fhirreference = sys.modules[__package__ + '.fhirreference'] 76 | try: 77 | from . import period 78 | except ImportError: 79 | period = sys.modules[__package__ + '.period'] -------------------------------------------------------------------------------- /docs/overview/creating_mappings.rst: -------------------------------------------------------------------------------- 1 | Creating Mappings 2 | ----------------- 3 | 4 | Fhirbug offers a simple declarative way to map your database tables to 5 | `Fhir Resources`_. You need to have created models for your tables using one of 6 | the supported ORMs. 7 | 8 | Let's see an example using SQLAlchemy. Suppose we have this model of our database 9 | table where patient personal infrormation is stored. 10 | 11 | (Note that we have named the model Patient. This allows Fhirbug to match it to the corresponding resource automatically. If we wanted to give it a different name, we would then have to define `__Resource__ = 'Patient'` after the `__tablename__`) 12 | 13 | :: 14 | 15 | from sqlalchemy import Column, Integer, String 16 | 17 | class Patient(Base): 18 | __tablename__ = "PatientEntries" 19 | 20 | id = Column(Integer, primary_key=True) 21 | name_first = Column(String) 22 | name_last = Column(String) 23 | gender = Column(Integer) # 0: unknown, 1:female, 2:male 24 | ssn = Column(Integer) 25 | 26 | To map this table to the `Patient`_ resource, we will make it inherit it :class:`fhirbug.db.backends.SQLAlchemy.FhirBaseModel` instead of Base. 27 | Then we add a class named **FhirMap** as a member and add all fhir fields we want to support using :mod:`Attributes`: 28 | 29 | .. note:: 30 | You do not need to put your FhirMap in the same class as your models. You could just as well extend it in a second class while using FhirBaseModel as a mixin. 31 | 32 | :: 33 | 34 | from sqlalchemy import Column, Integer, String 35 | from fhirbug.db.backends.SQLAlchemy import FhirBaseModel 36 | from fhirbug.models import Attribute, NameAttribute 37 | from fhirbug.db.backends.SQLAlchemy.searches import NumericSearch 38 | 39 | class Patient(FhirBaseModel): 40 | __tablename__ = "PatientEntries" 41 | 42 | pat_id = Column(Integer, primary_key=True) 43 | name_first = Column(String) 44 | name_last = Column(String) 45 | gender = Column(Integer) # 0: unknown, 1:female, 2:male, 3:other 46 | ssn = Column(Integer) 47 | 48 | @property 49 | def get_gender(self): 50 | genders = ['unknown', 'female', 'male', 'other'] 51 | return genders[self.gender] 52 | 53 | @set_gender.setter 54 | def set_gender(self, value): 55 | genders = {'unknown': 0, 'female': 1, 'male': 2, 'other': 3} 56 | self.gender = genders[value] 57 | 58 | class FhirMap: 59 | id = Attribute('pat_id', searcher=NumericSearch('pid')) 60 | name = NameAttribute(given_getter='name_first', family_getter='name_last') 61 | def get_name(instance): 62 | gender = Attribute('get_gender', 'set_gender') 63 | 64 | 65 | 66 | 67 | .. _`Fhir Resources`: https://www.hl7.org/fhir/resourcelist.html 68 | .. _`Patient`: https://www.hl7.org/fhir/patient.html 69 | -------------------------------------------------------------------------------- /fhirbug/Fhir/Resources/population.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Generated from FHIR 4.0.0-a53ec6ee1b (http://hl7.org/fhir/StructureDefinition/Population) on 2019-01-25. 5 | # 2019, SMART Health IT. 6 | ## 7 | 8 | 9 | from . import backboneelement 10 | 11 | class Population(backboneelement.BackboneElement): 12 | """ A definition of a set of people that apply to some clinically related 13 | context, for example people contraindicated for a certain medication. 14 | 15 | A populatioof people with some set of grouping criteria. 16 | """ 17 | 18 | resource_type = "Population" 19 | 20 | def __init__(self, jsondict=None, strict=True, **kwargs): 21 | """ Initialize all valid properties. 22 | 23 | :raises: FHIRValidationError on validation errors, unless strict is False 24 | :param dict jsondict: A JSON dictionary to use for initialization 25 | :param bool strict: If True (the default), invalid variables will raise a TypeError 26 | """ 27 | 28 | self.ageCodeableConcept = None 29 | """ The age of the specific population. 30 | Type `CodeableConcept` (represented as `dict` in JSON). """ 31 | 32 | self.ageRange = None 33 | """ The age of the specific population. 34 | Type `Range` (represented as `dict` in JSON). """ 35 | 36 | self.gender = None 37 | """ The gender of the specific population. 38 | Type `CodeableConcept` (represented as `dict` in JSON). """ 39 | 40 | self.physiologicalCondition = None 41 | """ The existing physiological conditions of the specific population to 42 | which this applies. 43 | Type `CodeableConcept` (represented as `dict` in JSON). """ 44 | 45 | self.race = None 46 | """ Race of the specific population. 47 | Type `CodeableConcept` (represented as `dict` in JSON). """ 48 | 49 | super(Population, self).__init__(jsondict=jsondict, strict=strict, **kwargs) 50 | 51 | def elementProperties(self): 52 | js = super(Population, self).elementProperties() 53 | js.extend([ 54 | ("ageCodeableConcept", "ageCodeableConcept", codeableconcept.CodeableConcept, False, "age", False), 55 | ("ageRange", "ageRange", range.Range, False, "age", False), 56 | ("gender", "gender", codeableconcept.CodeableConcept, False, None, False), 57 | ("physiologicalCondition", "physiologicalCondition", codeableconcept.CodeableConcept, False, None, False), 58 | ("race", "race", codeableconcept.CodeableConcept, False, None, False), 59 | ]) 60 | return js 61 | 62 | 63 | import sys 64 | try: 65 | from . import codeableconcept 66 | except ImportError: 67 | codeableconcept = sys.modules[__package__ + '.codeableconcept'] 68 | try: 69 | from . import range 70 | except ImportError: 71 | range = sys.modules[__package__ + '.range'] -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | 2 | Welcome to fhirbug's documentation! 3 | ==================================== 4 | 5 | Fhirbug intends to be a full-featured `FHIR`_ server for python >= **3.6**. It has been 6 | designed to be easy to set up and configure and be flexible when it comes to 7 | the rest of tools it is combined with, like web frameworks and database interfaces. 8 | In most simple cases, very little code has to be written apart from field 9 | mappings. 10 | 11 | **Fhirbug is still under development!** The API may still change at any time, 12 | it probably contains heaps of bugs and has never been tested in production. If 13 | you are interested in making it better, you are very welcome to contribute! 14 | 15 | **What fhirbug does:** 16 | 17 | 18 | - It provides the ability to create "real time" transformations between your ORM models to valid FHIR resources through an extensive mapping API. 19 | 20 | - Has been designed to work with existing data-sets and database schemas but can of course be used with its own database. 21 | 22 | - It's compatible with the SQLAlchemy_, DjangoORM_ and PyMODM_ ORMs, so if you can describe your database in one of them, you are good to go. It should also be pretty easy to extend to support any other ORM, feel free to submit a pull request! 23 | 24 | - Handles many of the FHIR REST operations and searches like creating and updating resources, performing advanced queries such as reverse includes, paginated bundles, contained or referenced resources, and more. 25 | 26 | - Provides the ability to audit each request, at the granularity that you desire, all the way down to limiting which of the attributes for each model should be accessible for each user. 27 | 28 | **What fhirbug does not do:** 29 | 30 | - Provide a ready to use solution for a Fhir server. Fhirbug is a framework, we want things to be as easy as possible but you will still have to write code. 31 | 32 | - Contain a web server. Fhirbug takes over once there is a request string and request body and returns a json object. You have to handle the actual requests and responses. 33 | 34 | - Handle authentication and authorization. It supports it, but you must write the implementation. 35 | 36 | - A ton of smaller stuff, which you can find in the Roadmap_. 37 | 38 | 39 | .. toctree:: 40 | :maxdepth: 3 41 | :caption: Contents: 42 | 43 | quickstart 44 | overview 45 | api_index 46 | examples/index 47 | 48 | 49 | Indices and tables 50 | ================== 51 | 52 | * :ref:`genindex` 53 | * :ref:`modindex` 54 | * :ref:`search` 55 | 56 | 57 | .. _fhir: https://www.hl7.org/fhir/ 58 | .. _flask: http://flask.pocoo.org/ 59 | .. _DjangoORM: https://www.djangoproject.com/ 60 | .. _PyMODM: https://github.com/mongodb/pymodm 61 | .. _SQLAlchemy: https://www.sqlalchemy.org/ 62 | .. _`search parameters`: https://www.hl7.org/fhir/searchparameter-registry.html 63 | .. _`Documents`: https://www.hl7.org/fhir/documents.html 64 | .. _`_at`: https://www.hl7.org/fhir/http.html#history 65 | -------------------------------------------------------------------------------- /fhirbug/Fhir/Resources/basic.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Generated from FHIR 4.0.0-a53ec6ee1b (http://hl7.org/fhir/StructureDefinition/Basic) on 2019-01-25. 5 | # 2019, SMART Health IT. 6 | ## 7 | 8 | 9 | from . import domainresource 10 | 11 | class Basic(domainresource.DomainResource): 12 | """ Resource for non-supported content. 13 | 14 | Basic is used for handling concepts not yet defined in FHIR, narrative-only 15 | resources that don't map to an existing resource, and custom resources not 16 | appropriate for inclusion in the FHIR specification. 17 | """ 18 | 19 | resource_type = "Basic" 20 | 21 | def __init__(self, jsondict=None, strict=True, **kwargs): 22 | """ Initialize all valid properties. 23 | 24 | :raises: FHIRValidationError on validation errors, unless strict is False 25 | :param dict jsondict: A JSON dictionary to use for initialization 26 | :param bool strict: If True (the default), invalid variables will raise a TypeError 27 | """ 28 | 29 | self.author = None 30 | """ Who created. 31 | Type `FHIRReference` (represented as `dict` in JSON). """ 32 | 33 | self.code = None 34 | """ Kind of Resource. 35 | Type `CodeableConcept` (represented as `dict` in JSON). """ 36 | 37 | self.created = None 38 | """ When created. 39 | Type `FHIRDate` (represented as `str` in JSON). """ 40 | 41 | self.identifier = None 42 | """ Business identifier. 43 | List of `Identifier` items (represented as `dict` in JSON). """ 44 | 45 | self.subject = None 46 | """ Identifies the focus of this resource. 47 | Type `FHIRReference` (represented as `dict` in JSON). """ 48 | 49 | super(Basic, self).__init__(jsondict=jsondict, strict=strict, **kwargs) 50 | 51 | def elementProperties(self): 52 | js = super(Basic, self).elementProperties() 53 | js.extend([ 54 | ("author", "author", fhirreference.FHIRReference, False, None, False), 55 | ("code", "code", codeableconcept.CodeableConcept, False, None, True), 56 | ("created", "created", fhirdate.FHIRDate, False, None, False), 57 | ("identifier", "identifier", identifier.Identifier, True, None, False), 58 | ("subject", "subject", fhirreference.FHIRReference, False, None, False), 59 | ]) 60 | return js 61 | 62 | 63 | import sys 64 | try: 65 | from . import codeableconcept 66 | except ImportError: 67 | codeableconcept = sys.modules[__package__ + '.codeableconcept'] 68 | try: 69 | from . import fhirdate 70 | except ImportError: 71 | fhirdate = sys.modules[__package__ + '.fhirdate'] 72 | try: 73 | from . import fhirreference 74 | except ImportError: 75 | fhirreference = sys.modules[__package__ + '.fhirreference'] 76 | try: 77 | from . import identifier 78 | except ImportError: 79 | identifier = sys.modules[__package__ + '.identifier'] -------------------------------------------------------------------------------- /examples/pymodm_autogenerated/flask_app.py: -------------------------------------------------------------------------------- 1 | import sys 2 | from pathlib import Path 3 | import json 4 | import dicttoxml 5 | import flask 6 | from flask import Flask, Response, render_template 7 | import pymodm 8 | 9 | try: 10 | from fhirbug.config import settings 11 | settings.configure("settings") 12 | from fhirbug.server import GetRequestHandler, PostRequestHandler, PutRequestHandler 13 | except ModuleNotFoundError: 14 | # Allow execution from a git clone without having fhirball installed. 15 | if Path('./fhirbug').is_dir(): # Executed from the example's directory` 16 | sys.path.append("./") 17 | elif Path('../../fhirbug').is_dir(): # Executed from the project's root directory` 18 | sys.path.append("../../") 19 | from fhirbug.config import settings 20 | settings.configure("settings") 21 | from fhirbug.server import GetRequestHandler, PostRequestHandler, PutRequestHandler 22 | 23 | 24 | pymodm.connect(settings.PYMODM_CONFIG["URI"]) 25 | 26 | app = Flask(__name__) 27 | app.config.update(debug=settings.DEBUG) 28 | 29 | 30 | @app.route("/r4/", defaults={"path": ""}) 31 | @app.route("/r4/", methods=["GET", "POST", "PUT"]) 32 | def request(path): 33 | url = flask.request.full_path[1:].partition("/")[2] 34 | request_headers = flask.request.headers 35 | 36 | # Handle GET requests 37 | if flask.request.method == "GET": 38 | handler = GetRequestHandler() 39 | content, status = handler.handle(url, query_context=flask.request) 40 | 41 | # Check the accept header and convert to the appropriate format 42 | resp_content, mimetype = convert_response_content(request_headers, url, content) 43 | return Response(resp_content, status, mimetype=mimetype) 44 | 45 | # Handle POST and PUT requests 46 | elif flask.request.method in ["POST", "PUT"]: 47 | body = flask.request.json 48 | method = flask.request.method 49 | handler = PostRequestHandler() if method == "POST" else PutRequestHandler() 50 | content, status = handler.handle(url, body) 51 | 52 | # Check the accept header and convert to the appropriate format 53 | resp_content, mimetype = convert_response_content(request_headers, url, content) 54 | return Response(resp_content, status, mimetype=mimetype) 55 | 56 | 57 | def convert_response_content(headers, url, content): 58 | """ 59 | Reads the request's ``Accept`` header and the _format query parameter 60 | and converts content to the appropriate type. 61 | 62 | returns a tuple (content, mime_type) 63 | """ 64 | if headers.get("Accept") == "application/xml" or "_format=xml" in url: 65 | return dicttoxml.dicttoxml(content), "text/xml" 66 | else: 67 | return json.dumps(content), "application/json" 68 | 69 | 70 | @app.route("/") 71 | def index(): 72 | ''' 73 | The index page 74 | ''' 75 | return render_template('index.html') 76 | 77 | 78 | if __name__ == "__main__": 79 | app.run(host='0.0.0.0', debug=settings.DEBUG) 80 | -------------------------------------------------------------------------------- /fhirbug/Fhir/Resources/medicinalproductundesirableeffect.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Generated from FHIR 4.0.0-a53ec6ee1b (http://hl7.org/fhir/StructureDefinition/MedicinalProductUndesirableEffect) on 2019-01-25. 5 | # 2019, SMART Health IT. 6 | ## 7 | 8 | 9 | from . import domainresource 10 | 11 | class MedicinalProductUndesirableEffect(domainresource.DomainResource): 12 | """ MedicinalProductUndesirableEffect. 13 | 14 | Describe the undesirable effects of the medicinal product. 15 | """ 16 | 17 | resource_type = "MedicinalProductUndesirableEffect" 18 | 19 | def __init__(self, jsondict=None, strict=True, **kwargs): 20 | """ Initialize all valid properties. 21 | 22 | :raises: FHIRValidationError on validation errors, unless strict is False 23 | :param dict jsondict: A JSON dictionary to use for initialization 24 | :param bool strict: If True (the default), invalid variables will raise a TypeError 25 | """ 26 | 27 | self.classification = None 28 | """ Classification of the effect. 29 | Type `CodeableConcept` (represented as `dict` in JSON). """ 30 | 31 | self.frequencyOfOccurrence = None 32 | """ The frequency of occurrence of the effect. 33 | Type `CodeableConcept` (represented as `dict` in JSON). """ 34 | 35 | self.population = None 36 | """ The population group to which this applies. 37 | List of `Population` items (represented as `dict` in JSON). """ 38 | 39 | self.subject = None 40 | """ The medication for which this is an indication. 41 | List of `FHIRReference` items (represented as `dict` in JSON). """ 42 | 43 | self.symptomConditionEffect = None 44 | """ The symptom, condition or undesirable effect. 45 | Type `CodeableConcept` (represented as `dict` in JSON). """ 46 | 47 | super(MedicinalProductUndesirableEffect, self).__init__(jsondict=jsondict, strict=strict, **kwargs) 48 | 49 | def elementProperties(self): 50 | js = super(MedicinalProductUndesirableEffect, self).elementProperties() 51 | js.extend([ 52 | ("classification", "classification", codeableconcept.CodeableConcept, False, None, False), 53 | ("frequencyOfOccurrence", "frequencyOfOccurrence", codeableconcept.CodeableConcept, False, None, False), 54 | ("population", "population", population.Population, True, None, False), 55 | ("subject", "subject", fhirreference.FHIRReference, True, None, False), 56 | ("symptomConditionEffect", "symptomConditionEffect", codeableconcept.CodeableConcept, False, None, False), 57 | ]) 58 | return js 59 | 60 | 61 | import sys 62 | try: 63 | from . import codeableconcept 64 | except ImportError: 65 | codeableconcept = sys.modules[__package__ + '.codeableconcept'] 66 | try: 67 | from . import fhirreference 68 | except ImportError: 69 | fhirreference = sys.modules[__package__ + '.fhirreference'] 70 | try: 71 | from . import population 72 | except ImportError: 73 | population = sys.modules[__package__ + '.population'] -------------------------------------------------------------------------------- /fhirbug/Fhir/Resources/enrollmentrequest.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Generated from FHIR 4.0.0-a53ec6ee1b (http://hl7.org/fhir/StructureDefinition/EnrollmentRequest) on 2019-01-25. 5 | # 2019, SMART Health IT. 6 | ## 7 | 8 | 9 | from . import domainresource 10 | 11 | class EnrollmentRequest(domainresource.DomainResource): 12 | """ Enroll in coverage. 13 | 14 | This resource provides the insurance enrollment details to the insurer 15 | regarding a specified coverage. 16 | """ 17 | 18 | resource_type = "EnrollmentRequest" 19 | 20 | def __init__(self, jsondict=None, strict=True, **kwargs): 21 | """ Initialize all valid properties. 22 | 23 | :raises: FHIRValidationError on validation errors, unless strict is False 24 | :param dict jsondict: A JSON dictionary to use for initialization 25 | :param bool strict: If True (the default), invalid variables will raise a TypeError 26 | """ 27 | 28 | self.candidate = None 29 | """ The subject to be enrolled. 30 | Type `FHIRReference` (represented as `dict` in JSON). """ 31 | 32 | self.coverage = None 33 | """ Insurance information. 34 | Type `FHIRReference` (represented as `dict` in JSON). """ 35 | 36 | self.created = None 37 | """ Creation date. 38 | Type `FHIRDate` (represented as `str` in JSON). """ 39 | 40 | self.identifier = None 41 | """ Business Identifier. 42 | List of `Identifier` items (represented as `dict` in JSON). """ 43 | 44 | self.insurer = None 45 | """ Target. 46 | Type `FHIRReference` (represented as `dict` in JSON). """ 47 | 48 | self.provider = None 49 | """ Responsible practitioner. 50 | Type `FHIRReference` (represented as `dict` in JSON). """ 51 | 52 | self.status = None 53 | """ active | cancelled | draft | entered-in-error. 54 | Type `str`. """ 55 | 56 | super(EnrollmentRequest, self).__init__(jsondict=jsondict, strict=strict, **kwargs) 57 | 58 | def elementProperties(self): 59 | js = super(EnrollmentRequest, self).elementProperties() 60 | js.extend([ 61 | ("candidate", "candidate", fhirreference.FHIRReference, False, None, False), 62 | ("coverage", "coverage", fhirreference.FHIRReference, False, None, False), 63 | ("created", "created", fhirdate.FHIRDate, False, None, False), 64 | ("identifier", "identifier", identifier.Identifier, True, None, False), 65 | ("insurer", "insurer", fhirreference.FHIRReference, False, None, False), 66 | ("provider", "provider", fhirreference.FHIRReference, False, None, False), 67 | ("status", "status", str, False, None, False), 68 | ]) 69 | return js 70 | 71 | 72 | import sys 73 | try: 74 | from . import fhirdate 75 | except ImportError: 76 | fhirdate = sys.modules[__package__ + '.fhirdate'] 77 | try: 78 | from . import fhirreference 79 | except ImportError: 80 | fhirreference = sys.modules[__package__ + '.fhirreference'] 81 | try: 82 | from . import identifier 83 | except ImportError: 84 | identifier = sys.modules[__package__ + '.identifier'] -------------------------------------------------------------------------------- /fhirbug/Fhir/base/fhirdate.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Facilitate working with dates. 5 | # 2014, SMART Health IT. 6 | 7 | import sys 8 | import logging 9 | import isodate 10 | import datetime 11 | 12 | logger = logging.getLogger(__name__) 13 | 14 | 15 | class FHIRDate(object): 16 | """ Facilitate working with dates. 17 | 18 | - `date`: datetime object representing the receiver's date-time 19 | """ 20 | 21 | def __init__(self, jsonval=None): 22 | self.date = None 23 | if jsonval is not None: 24 | 25 | ## Accept python datetime types 26 | if isinstance(jsonval, datetime.date) or isinstance(jsonval, datetime.datetime): 27 | self.date = jsonval 28 | self.origval = self.isostring 29 | return 30 | 31 | # Validate strings 32 | isstr = isinstance(jsonval, str) 33 | if not isstr and sys.version_info[0] < 3: # Python 2.x has 'str' and 'unicode' 34 | isstr = isinstance(jsonval, basestring) 35 | if not isstr: 36 | raise TypeError("Expecting string when initializing {}, but got {}" 37 | .format(type(self), type(jsonval))) 38 | 39 | # Parse the dates 40 | try: 41 | if 'T' in jsonval: 42 | self.date = isodate.parse_datetime(jsonval) 43 | else: 44 | self.date = isodate.parse_date(jsonval) 45 | except Exception as e: 46 | logger.warning("Failed to initialize FHIRDate from \"{}\": {}" 47 | .format(jsonval, e)) 48 | 49 | self.origval = jsonval 50 | 51 | def __setattr__(self, prop, value): 52 | if 'date' == prop: 53 | self.origval = None 54 | object.__setattr__(self, prop, value) 55 | 56 | @property 57 | def isostring(self): 58 | if self.date is None: 59 | return None 60 | if isinstance(self.date, datetime.datetime): 61 | return isodate.datetime_isoformat(self.date) 62 | return isodate.date_isoformat(self.date) 63 | 64 | @classmethod 65 | def with_json(cls, jsonobj): 66 | """ Initialize a date from an ISO date string. 67 | """ 68 | ## Allow use in other resources 69 | if isinstance(jsonobj, cls): 70 | return jsonobj 71 | 72 | isstr = isinstance(jsonobj, str) 73 | if not isstr and sys.version_info[0] < 3: # Python 2.x has 'str' and 'unicode' 74 | isstr = isinstance(jsonobj, basestring) 75 | if isstr: 76 | return cls(jsonobj) 77 | 78 | if isinstance(jsonobj, list): 79 | return [cls(jsonval) for jsonval in jsonobj] 80 | 81 | raise TypeError("`cls.with_json()` only takes string or list of strings, but you provided {}" 82 | .format(type(jsonobj))) 83 | 84 | @classmethod 85 | def with_json_and_owner(cls, jsonobj, owner): 86 | """ Added for compatibility reasons to FHIRElement; "owner" is 87 | discarded. 88 | """ 89 | return cls.with_json(jsonobj) 90 | 91 | def as_json(self): 92 | if self.origval is not None: 93 | return self.origval 94 | return self.isostring 95 | -------------------------------------------------------------------------------- /fhirbug/Fhir/Resources/fhirdate.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Facilitate working with dates. 5 | # 2014, SMART Health IT. 6 | 7 | import sys 8 | import logging 9 | import isodate 10 | import datetime 11 | 12 | logger = logging.getLogger(__name__) 13 | 14 | 15 | class FHIRDate(object): 16 | """ Facilitate working with dates. 17 | 18 | - `date`: datetime object representing the receiver's date-time 19 | """ 20 | 21 | def __init__(self, jsonval=None): 22 | self.date = None 23 | if jsonval is not None: 24 | 25 | ## Accept python datetime types 26 | if isinstance(jsonval, datetime.date) or isinstance(jsonval, datetime.datetime): 27 | self.date = jsonval 28 | self.origval = self.isostring 29 | return 30 | 31 | # Validate strings 32 | isstr = isinstance(jsonval, str) 33 | if not isstr and sys.version_info[0] < 3: # Python 2.x has 'str' and 'unicode' 34 | isstr = isinstance(jsonval, basestring) 35 | if not isstr: 36 | raise TypeError("Expecting string when initializing {}, but got {}" 37 | .format(type(self), type(jsonval))) 38 | 39 | # Parse the dates 40 | try: 41 | if 'T' in jsonval: 42 | self.date = isodate.parse_datetime(jsonval) 43 | else: 44 | self.date = isodate.parse_date(jsonval) 45 | except Exception as e: 46 | logger.warning("Failed to initialize FHIRDate from \"{}\": {}" 47 | .format(jsonval, e)) 48 | 49 | self.origval = jsonval 50 | 51 | def __setattr__(self, prop, value): 52 | if 'date' == prop: 53 | self.origval = None 54 | object.__setattr__(self, prop, value) 55 | 56 | @property 57 | def isostring(self): 58 | if self.date is None: 59 | return None 60 | if isinstance(self.date, datetime.datetime): 61 | return isodate.datetime_isoformat(self.date) 62 | return isodate.date_isoformat(self.date) 63 | 64 | @classmethod 65 | def with_json(cls, jsonobj): 66 | """ Initialize a date from an ISO date string. 67 | """ 68 | ## Allow use in other resources 69 | if isinstance(jsonobj, cls): 70 | return jsonobj 71 | 72 | isstr = isinstance(jsonobj, str) 73 | if not isstr and sys.version_info[0] < 3: # Python 2.x has 'str' and 'unicode' 74 | isstr = isinstance(jsonobj, basestring) 75 | if isstr: 76 | return cls(jsonobj) 77 | 78 | if isinstance(jsonobj, list): 79 | return [cls(jsonval) for jsonval in jsonobj] 80 | 81 | raise TypeError("`cls.with_json()` only takes string or list of strings, but you provided {}" 82 | .format(type(jsonobj))) 83 | 84 | @classmethod 85 | def with_json_and_owner(cls, jsonobj, owner): 86 | """ Added for compatibility reasons to FHIRElement; "owner" is 87 | discarded. 88 | """ 89 | return cls.with_json(jsonobj) 90 | 91 | def as_json(self): 92 | if self.origval is not None: 93 | return self.origval 94 | return self.isostring 95 | -------------------------------------------------------------------------------- /fhirbug/Fhir/Resources/usagecontext.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Generated from FHIR 4.0.0-a53ec6ee1b (http://hl7.org/fhir/StructureDefinition/UsageContext) on 2019-01-25. 5 | # 2019, SMART Health IT. 6 | ## 7 | 8 | 9 | from . import element 10 | 11 | class UsageContext(element.Element): 12 | """ Describes the context of use for a conformance or knowledge resource. 13 | 14 | Specifies clinical/business/etc. metadata that can be used to retrieve, 15 | index and/or categorize an artifact. This metadata can either be specific 16 | to the applicable population (e.g., age category, DRG) or the specific 17 | context of care (e.g., venue, care setting, provider of care). 18 | """ 19 | 20 | resource_type = "UsageContext" 21 | 22 | def __init__(self, jsondict=None, strict=True, **kwargs): 23 | """ Initialize all valid properties. 24 | 25 | :raises: FHIRValidationError on validation errors, unless strict is False 26 | :param dict jsondict: A JSON dictionary to use for initialization 27 | :param bool strict: If True (the default), invalid variables will raise a TypeError 28 | """ 29 | 30 | self.code = None 31 | """ Type of context being specified. 32 | Type `Coding` (represented as `dict` in JSON). """ 33 | 34 | self.valueCodeableConcept = None 35 | """ Value that defines the context. 36 | Type `CodeableConcept` (represented as `dict` in JSON). """ 37 | 38 | self.valueQuantity = None 39 | """ Value that defines the context. 40 | Type `Quantity` (represented as `dict` in JSON). """ 41 | 42 | self.valueRange = None 43 | """ Value that defines the context. 44 | Type `Range` (represented as `dict` in JSON). """ 45 | 46 | self.valueReference = None 47 | """ Value that defines the context. 48 | Type `FHIRReference` (represented as `dict` in JSON). """ 49 | 50 | super(UsageContext, self).__init__(jsondict=jsondict, strict=strict, **kwargs) 51 | 52 | def elementProperties(self): 53 | js = super(UsageContext, self).elementProperties() 54 | js.extend([ 55 | ("code", "code", coding.Coding, False, None, True), 56 | ("valueCodeableConcept", "valueCodeableConcept", codeableconcept.CodeableConcept, False, "value", True), 57 | ("valueQuantity", "valueQuantity", quantity.Quantity, False, "value", True), 58 | ("valueRange", "valueRange", range.Range, False, "value", True), 59 | ("valueReference", "valueReference", fhirreference.FHIRReference, False, "value", True), 60 | ]) 61 | return js 62 | 63 | 64 | import sys 65 | try: 66 | from . import codeableconcept 67 | except ImportError: 68 | codeableconcept = sys.modules[__package__ + '.codeableconcept'] 69 | try: 70 | from . import coding 71 | except ImportError: 72 | coding = sys.modules[__package__ + '.coding'] 73 | try: 74 | from . import fhirreference 75 | except ImportError: 76 | fhirreference = sys.modules[__package__ + '.fhirreference'] 77 | try: 78 | from . import quantity 79 | except ImportError: 80 | quantity = sys.modules[__package__ + '.quantity'] 81 | try: 82 | from . import range 83 | except ImportError: 84 | range = sys.modules[__package__ + '.range'] -------------------------------------------------------------------------------- /fhirbug/Fhir/base/template-resource.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Generated from FHIR {{ info.version }} ({{ profile.url }}) on {{ info.date }}. 5 | # {{ info.year }}, SMART Health IT. 6 | ## 7 | 8 | {%- set imported = {} %} 9 | {%- for klass in classes %} 10 | 11 | 12 | {% if klass.superclass in imports and klass.superclass.module not in imported -%} 13 | from . import {{ klass.superclass.module }} 14 | {% set _ = imported.update({klass.superclass.module: True}) %} 15 | {% endif -%} 16 | 17 | class {{ klass.name }}({% if klass.superclass in imports %}{{ klass.superclass.module }}.{% endif -%} 18 | {{ klass.superclass.name|default('object')}}): 19 | """ {{ klass.short|wordwrap(width=75, wrapstring="\n ") }}. 20 | {%- if klass.formal %} 21 | 22 | {{ klass.formal|wordwrap(width=75, wrapstring="\n ") }} 23 | {%- endif %} 24 | """ 25 | {%- if klass.resource_type %} 26 | 27 | resource_type = "{{ klass.resource_type }}" 28 | {%- endif %} 29 | 30 | def __init__(self, jsondict=None, strict=True, **kwargs): 31 | """ Initialize all valid properties. 32 | 33 | :raises: FHIRValidationError on validation errors, unless strict is False 34 | :param dict jsondict: A JSON dictionary to use for initialization 35 | :param bool strict: If True (the default), invalid variables will raise a TypeError 36 | """ 37 | {%- for prop in klass.properties %} 38 | 39 | self.{{ prop.name }} = None 40 | """ {{ prop.short|wordwrap(67, wrapstring="\n ") }}. 41 | {% if prop.is_array %}List of{% else %}Type{% endif %} `{{ prop.class_name }}`{% if prop.is_array %} items{% endif %} 42 | {%- if prop.reference_to_names|length > 0 %} referencing `{{ prop.reference_to_names|join(', ') }}`{% endif %} 43 | {%- if prop.json_class != prop.class_name %} (represented as `{{ prop.json_class }}` in JSON){% endif %}. """ 44 | {%- endfor %} 45 | 46 | super({{ klass.name }}, self).__init__(jsondict=jsondict, strict=strict, **kwargs) 47 | 48 | {%- if klass.properties %} 49 | 50 | def elementProperties(self): 51 | js = super({{ klass.name }}, self).elementProperties() 52 | {%- if 'element' == klass.module and 'Element' == klass.name %} 53 | {%- for imp in imports %}{% if imp.module not in imported %} 54 | from . import {{ imp.module }} 55 | {%- set _ = imported.update({imp.module: True}) %} 56 | {%- endif %}{% endfor %} 57 | {%- endif %} 58 | js.extend([ 59 | {%- for prop in klass.properties %} 60 | ("{{ prop.name }}", "{{ prop.orig_name }}", 61 | {%- if prop.module_name %} {{ prop.module_name }}.{% else %} {% endif %}{{ prop.class_name }}, {# #} 62 | {{- prop.is_array }}, 63 | {%- if prop.one_of_many %} "{{ prop.one_of_many }}"{% else %} None{% endif %}, {# #} 64 | {{- prop.nonoptional }}), 65 | {%- endfor %} 66 | ]) 67 | return js 68 | 69 | {%- endif %} 70 | {%- endfor %} 71 | 72 | {% if imports|length > 0 and imported|length != imports|length %} 73 | import sys 74 | {%- endif %} 75 | {%- for imp in imports %}{% if imp.module not in imported %} 76 | try: 77 | from . import {{ imp.module }} 78 | except ImportError: 79 | {{ imp.module }} = sys.modules[__package__ + '.{{ imp.module }}'] 80 | {%- endif %}{% endfor %} 81 | -------------------------------------------------------------------------------- /fhirbug/Fhir/Resources/enrollmentresponse.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Generated from FHIR 4.0.0-a53ec6ee1b (http://hl7.org/fhir/StructureDefinition/EnrollmentResponse) on 2019-01-25. 5 | # 2019, SMART Health IT. 6 | ## 7 | 8 | 9 | from . import domainresource 10 | 11 | class EnrollmentResponse(domainresource.DomainResource): 12 | """ EnrollmentResponse resource. 13 | 14 | This resource provides enrollment and plan details from the processing of 15 | an EnrollmentRequest resource. 16 | """ 17 | 18 | resource_type = "EnrollmentResponse" 19 | 20 | def __init__(self, jsondict=None, strict=True, **kwargs): 21 | """ Initialize all valid properties. 22 | 23 | :raises: FHIRValidationError on validation errors, unless strict is False 24 | :param dict jsondict: A JSON dictionary to use for initialization 25 | :param bool strict: If True (the default), invalid variables will raise a TypeError 26 | """ 27 | 28 | self.created = None 29 | """ Creation date. 30 | Type `FHIRDate` (represented as `str` in JSON). """ 31 | 32 | self.disposition = None 33 | """ Disposition Message. 34 | Type `str`. """ 35 | 36 | self.identifier = None 37 | """ Business Identifier. 38 | List of `Identifier` items (represented as `dict` in JSON). """ 39 | 40 | self.organization = None 41 | """ Insurer. 42 | Type `FHIRReference` (represented as `dict` in JSON). """ 43 | 44 | self.outcome = None 45 | """ queued | complete | error | partial. 46 | Type `str`. """ 47 | 48 | self.request = None 49 | """ Claim reference. 50 | Type `FHIRReference` (represented as `dict` in JSON). """ 51 | 52 | self.requestProvider = None 53 | """ Responsible practitioner. 54 | Type `FHIRReference` (represented as `dict` in JSON). """ 55 | 56 | self.status = None 57 | """ active | cancelled | draft | entered-in-error. 58 | Type `str`. """ 59 | 60 | super(EnrollmentResponse, self).__init__(jsondict=jsondict, strict=strict, **kwargs) 61 | 62 | def elementProperties(self): 63 | js = super(EnrollmentResponse, self).elementProperties() 64 | js.extend([ 65 | ("created", "created", fhirdate.FHIRDate, False, None, False), 66 | ("disposition", "disposition", str, False, None, False), 67 | ("identifier", "identifier", identifier.Identifier, True, None, False), 68 | ("organization", "organization", fhirreference.FHIRReference, False, None, False), 69 | ("outcome", "outcome", str, False, None, False), 70 | ("request", "request", fhirreference.FHIRReference, False, None, False), 71 | ("requestProvider", "requestProvider", fhirreference.FHIRReference, False, None, False), 72 | ("status", "status", str, False, None, False), 73 | ]) 74 | return js 75 | 76 | 77 | import sys 78 | try: 79 | from . import fhirdate 80 | except ImportError: 81 | fhirdate = sys.modules[__package__ + '.fhirdate'] 82 | try: 83 | from . import fhirreference 84 | except ImportError: 85 | fhirreference = sys.modules[__package__ + '.fhirreference'] 86 | try: 87 | from . import identifier 88 | except ImportError: 89 | identifier = sys.modules[__package__ + '.identifier'] -------------------------------------------------------------------------------- /fhirbug/Fhir/Resources/signature.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Generated from FHIR 4.0.0-a53ec6ee1b (http://hl7.org/fhir/StructureDefinition/Signature) on 2019-01-25. 5 | # 2019, SMART Health IT. 6 | ## 7 | 8 | 9 | from . import element 10 | 11 | class Signature(element.Element): 12 | """ A Signature - XML DigSig, JWS, Graphical image of signature, etc.. 13 | 14 | A signature along with supporting context. The signature may be a digital 15 | signature that is cryptographic in nature, or some other signature 16 | acceptable to the domain. This other signature may be as simple as a 17 | graphical image representing a hand-written signature, or a signature 18 | ceremony Different signature approaches have different utilities. 19 | """ 20 | 21 | resource_type = "Signature" 22 | 23 | def __init__(self, jsondict=None, strict=True, **kwargs): 24 | """ Initialize all valid properties. 25 | 26 | :raises: FHIRValidationError on validation errors, unless strict is False 27 | :param dict jsondict: A JSON dictionary to use for initialization 28 | :param bool strict: If True (the default), invalid variables will raise a TypeError 29 | """ 30 | 31 | self.data = None 32 | """ The actual signature content (XML DigSig. JWS, picture, etc.). 33 | Type `str`. """ 34 | 35 | self.onBehalfOf = None 36 | """ The party represented. 37 | Type `FHIRReference` (represented as `dict` in JSON). """ 38 | 39 | self.sigFormat = None 40 | """ The technical format of the signature. 41 | Type `str`. """ 42 | 43 | self.targetFormat = None 44 | """ The technical format of the signed resources. 45 | Type `str`. """ 46 | 47 | self.type = None 48 | """ Indication of the reason the entity signed the object(s). 49 | List of `Coding` items (represented as `dict` in JSON). """ 50 | 51 | self.when = None 52 | """ When the signature was created. 53 | Type `FHIRDate` (represented as `str` in JSON). """ 54 | 55 | self.who = None 56 | """ Who signed. 57 | Type `FHIRReference` (represented as `dict` in JSON). """ 58 | 59 | super(Signature, self).__init__(jsondict=jsondict, strict=strict, **kwargs) 60 | 61 | def elementProperties(self): 62 | js = super(Signature, self).elementProperties() 63 | js.extend([ 64 | ("data", "data", str, False, None, False), 65 | ("onBehalfOf", "onBehalfOf", fhirreference.FHIRReference, False, None, False), 66 | ("sigFormat", "sigFormat", str, False, None, False), 67 | ("targetFormat", "targetFormat", str, False, None, False), 68 | ("type", "type", coding.Coding, True, None, True), 69 | ("when", "when", fhirdate.FHIRDate, False, None, True), 70 | ("who", "who", fhirreference.FHIRReference, False, None, True), 71 | ]) 72 | return js 73 | 74 | 75 | import sys 76 | try: 77 | from . import coding 78 | except ImportError: 79 | coding = sys.modules[__package__ + '.coding'] 80 | try: 81 | from . import fhirdate 82 | except ImportError: 83 | fhirdate = sys.modules[__package__ + '.fhirdate'] 84 | try: 85 | from . import fhirreference 86 | except ImportError: 87 | fhirreference = sys.modules[__package__ + '.fhirreference'] -------------------------------------------------------------------------------- /fhirbug/Fhir/Resources/bodysite.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Generated from FHIR 3.0.1.11917 (http://hl7.org/fhir/StructureDefinition/BodySite) on 2019-01-25. 5 | # 2019, SMART Health IT. 6 | ## 7 | 8 | 9 | from . import domainresource 10 | 11 | class BodySite(domainresource.DomainResource): 12 | """ Specific and identified anatomical location. 13 | 14 | Record details about the anatomical location of a specimen or body part. 15 | This resource may be used when a coded concept does not provide the 16 | necessary detail needed for the use case. 17 | """ 18 | 19 | resource_type = "BodySite" 20 | 21 | def __init__(self, jsondict=None, strict=True, **kwargs): 22 | """ Initialize all valid properties. 23 | 24 | :raises: FHIRValidationError on validation errors, unless strict is False 25 | :param dict jsondict: A JSON dictionary to use for initialization 26 | :param bool strict: If True (the default), invalid variables will raise a TypeError 27 | """ 28 | 29 | self.active = None 30 | """ Whether this body site record is in active use. 31 | Type `bool`. """ 32 | 33 | self.code = None 34 | """ Named anatomical location. 35 | Type `CodeableConcept` (represented as `dict` in JSON). """ 36 | 37 | self.description = None 38 | """ Anatomical location description. 39 | Type `str`. """ 40 | 41 | self.identifier = None 42 | """ Bodysite identifier. 43 | List of `Identifier` items (represented as `dict` in JSON). """ 44 | 45 | self.image = None 46 | """ Attached images. 47 | List of `Attachment` items (represented as `dict` in JSON). """ 48 | 49 | self.patient = None 50 | """ Who this is about. 51 | Type `FHIRReference` referencing `Patient` (represented as `dict` in JSON). """ 52 | 53 | self.qualifier = None 54 | """ Modification to location code. 55 | List of `CodeableConcept` items (represented as `dict` in JSON). """ 56 | 57 | super(BodySite, self).__init__(jsondict=jsondict, strict=strict, **kwargs) 58 | 59 | def elementProperties(self): 60 | js = super(BodySite, self).elementProperties() 61 | js.extend([ 62 | ("active", "active", bool, False, None, False), 63 | ("code", "code", codeableconcept.CodeableConcept, False, None, False), 64 | ("description", "description", str, False, None, False), 65 | ("identifier", "identifier", identifier.Identifier, True, None, False), 66 | ("image", "image", attachment.Attachment, True, None, False), 67 | ("patient", "patient", fhirreference.FHIRReference, False, None, True), 68 | ("qualifier", "qualifier", codeableconcept.CodeableConcept, True, None, False), 69 | ]) 70 | return js 71 | 72 | 73 | import sys 74 | try: 75 | from . import attachment 76 | except ImportError: 77 | attachment = sys.modules[__package__ + '.attachment'] 78 | try: 79 | from . import codeableconcept 80 | except ImportError: 81 | codeableconcept = sys.modules[__package__ + '.codeableconcept'] 82 | try: 83 | from . import fhirreference 84 | except ImportError: 85 | fhirreference = sys.modules[__package__ + '.fhirreference'] 86 | try: 87 | from . import identifier 88 | except ImportError: 89 | identifier = sys.modules[__package__ + '.identifier'] -------------------------------------------------------------------------------- /fhirbug/Fhir/Resources/linkage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Generated from FHIR 4.0.0-a53ec6ee1b (http://hl7.org/fhir/StructureDefinition/Linkage) on 2019-01-25. 5 | # 2019, SMART Health IT. 6 | ## 7 | 8 | 9 | from . import domainresource 10 | 11 | class Linkage(domainresource.DomainResource): 12 | """ Links records for 'same' item. 13 | 14 | Identifies two or more records (resource instances) that refer to the same 15 | real-world "occurrence". 16 | """ 17 | 18 | resource_type = "Linkage" 19 | 20 | def __init__(self, jsondict=None, strict=True, **kwargs): 21 | """ Initialize all valid properties. 22 | 23 | :raises: FHIRValidationError on validation errors, unless strict is False 24 | :param dict jsondict: A JSON dictionary to use for initialization 25 | :param bool strict: If True (the default), invalid variables will raise a TypeError 26 | """ 27 | 28 | self.active = None 29 | """ Whether this linkage assertion is active or not. 30 | Type `bool`. """ 31 | 32 | self.author = None 33 | """ Who is responsible for linkages. 34 | Type `FHIRReference` (represented as `dict` in JSON). """ 35 | 36 | self.item = None 37 | """ Item to be linked. 38 | List of `LinkageItem` items (represented as `dict` in JSON). """ 39 | 40 | super(Linkage, self).__init__(jsondict=jsondict, strict=strict, **kwargs) 41 | 42 | def elementProperties(self): 43 | js = super(Linkage, self).elementProperties() 44 | js.extend([ 45 | ("active", "active", bool, False, None, False), 46 | ("author", "author", fhirreference.FHIRReference, False, None, False), 47 | ("item", "item", LinkageItem, True, None, True), 48 | ]) 49 | return js 50 | 51 | 52 | from . import backboneelement 53 | 54 | class LinkageItem(backboneelement.BackboneElement): 55 | """ Item to be linked. 56 | 57 | Identifies which record considered as the reference to the same real-world 58 | occurrence as well as how the items should be evaluated within the 59 | collection of linked items. 60 | """ 61 | 62 | resource_type = "LinkageItem" 63 | 64 | def __init__(self, jsondict=None, strict=True, **kwargs): 65 | """ Initialize all valid properties. 66 | 67 | :raises: FHIRValidationError on validation errors, unless strict is False 68 | :param dict jsondict: A JSON dictionary to use for initialization 69 | :param bool strict: If True (the default), invalid variables will raise a TypeError 70 | """ 71 | 72 | self.resource = None 73 | """ Resource being linked. 74 | Type `FHIRReference` (represented as `dict` in JSON). """ 75 | 76 | self.type = None 77 | """ source | alternate | historical. 78 | Type `str`. """ 79 | 80 | super(LinkageItem, self).__init__(jsondict=jsondict, strict=strict, **kwargs) 81 | 82 | def elementProperties(self): 83 | js = super(LinkageItem, self).elementProperties() 84 | js.extend([ 85 | ("resource", "resource", fhirreference.FHIRReference, False, None, True), 86 | ("type", "type", str, False, None, True), 87 | ]) 88 | return js 89 | 90 | 91 | import sys 92 | try: 93 | from . import fhirreference 94 | except ImportError: 95 | fhirreference = sys.modules[__package__ + '.fhirreference'] -------------------------------------------------------------------------------- /fhirbug/Fhir/Resources/address.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Generated from FHIR 4.0.0-a53ec6ee1b (http://hl7.org/fhir/StructureDefinition/Address) on 2019-01-25. 5 | # 2019, SMART Health IT. 6 | ## 7 | 8 | 9 | from . import element 10 | 11 | class Address(element.Element): 12 | """ An address expressed using postal conventions (as opposed to GPS or other 13 | location definition formats). 14 | 15 | An address expressed using postal conventions (as opposed to GPS or other 16 | location definition formats). This data type may be used to convey 17 | addresses for use in delivering mail as well as for visiting locations 18 | which might not be valid for mail delivery. There are a variety of postal 19 | address formats defined around the world. 20 | """ 21 | 22 | resource_type = "Address" 23 | 24 | def __init__(self, jsondict=None, strict=True, **kwargs): 25 | """ Initialize all valid properties. 26 | 27 | :raises: FHIRValidationError on validation errors, unless strict is False 28 | :param dict jsondict: A JSON dictionary to use for initialization 29 | :param bool strict: If True (the default), invalid variables will raise a TypeError 30 | """ 31 | 32 | self.city = None 33 | """ Name of city, town etc.. 34 | Type `str`. """ 35 | 36 | self.country = None 37 | """ Country (e.g. can be ISO 3166 2 or 3 letter code). 38 | Type `str`. """ 39 | 40 | self.district = None 41 | """ District name (aka county). 42 | Type `str`. """ 43 | 44 | self.line = None 45 | """ Street name, number, direction & P.O. Box etc.. 46 | List of `str` items. """ 47 | 48 | self.period = None 49 | """ Time period when address was/is in use. 50 | Type `Period` (represented as `dict` in JSON). """ 51 | 52 | self.postalCode = None 53 | """ Postal code for area. 54 | Type `str`. """ 55 | 56 | self.state = None 57 | """ Sub-unit of country (abbreviations ok). 58 | Type `str`. """ 59 | 60 | self.text = None 61 | """ Text representation of the address. 62 | Type `str`. """ 63 | 64 | self.type = None 65 | """ postal | physical | both. 66 | Type `str`. """ 67 | 68 | self.use = None 69 | """ home | work | temp | old | billing - purpose of this address. 70 | Type `str`. """ 71 | 72 | super(Address, self).__init__(jsondict=jsondict, strict=strict, **kwargs) 73 | 74 | def elementProperties(self): 75 | js = super(Address, self).elementProperties() 76 | js.extend([ 77 | ("city", "city", str, False, None, False), 78 | ("country", "country", str, False, None, False), 79 | ("district", "district", str, False, None, False), 80 | ("line", "line", str, True, None, False), 81 | ("period", "period", period.Period, False, None, False), 82 | ("postalCode", "postalCode", str, False, None, False), 83 | ("state", "state", str, False, None, False), 84 | ("text", "text", str, False, None, False), 85 | ("type", "type", str, False, None, False), 86 | ("use", "use", str, False, None, False), 87 | ]) 88 | return js 89 | 90 | 91 | import sys 92 | try: 93 | from . import period 94 | except ImportError: 95 | period = sys.modules[__package__ + '.period'] -------------------------------------------------------------------------------- /fhirbug/Fhir/Resources/productshelflife.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Generated from FHIR 4.0.0-a53ec6ee1b (http://hl7.org/fhir/StructureDefinition/ProductShelfLife) on 2019-01-25. 5 | # 2019, SMART Health IT. 6 | ## 7 | 8 | 9 | from . import backboneelement 10 | 11 | class ProductShelfLife(backboneelement.BackboneElement): 12 | """ The shelf-life and storage information for a medicinal product item or 13 | container can be described using this class. 14 | """ 15 | 16 | resource_type = "ProductShelfLife" 17 | 18 | def __init__(self, jsondict=None, strict=True, **kwargs): 19 | """ Initialize all valid properties. 20 | 21 | :raises: FHIRValidationError on validation errors, unless strict is False 22 | :param dict jsondict: A JSON dictionary to use for initialization 23 | :param bool strict: If True (the default), invalid variables will raise a TypeError 24 | """ 25 | 26 | self.identifier = None 27 | """ Unique identifier for the packaged Medicinal Product. 28 | Type `Identifier` (represented as `dict` in JSON). """ 29 | 30 | self.period = None 31 | """ The shelf life time period can be specified using a numerical value 32 | for the period of time and its unit of time measurement The unit of 33 | measurement shall be specified in accordance with ISO 11240 and the 34 | resulting terminology The symbol and the symbol identifier shall be 35 | used. 36 | Type `Quantity` (represented as `dict` in JSON). """ 37 | 38 | self.specialPrecautionsForStorage = None 39 | """ Special precautions for storage, if any, can be specified using an 40 | appropriate controlled vocabulary The controlled term and the 41 | controlled term identifier shall be specified. 42 | List of `CodeableConcept` items (represented as `dict` in JSON). """ 43 | 44 | self.type = None 45 | """ This describes the shelf life, taking into account various 46 | scenarios such as shelf life of the packaged Medicinal Product 47 | itself, shelf life after transformation where necessary and shelf 48 | life after the first opening of a bottle, etc. The shelf life type 49 | shall be specified using an appropriate controlled vocabulary The 50 | controlled term and the controlled term identifier shall be 51 | specified. 52 | Type `CodeableConcept` (represented as `dict` in JSON). """ 53 | 54 | super(ProductShelfLife, self).__init__(jsondict=jsondict, strict=strict, **kwargs) 55 | 56 | def elementProperties(self): 57 | js = super(ProductShelfLife, self).elementProperties() 58 | js.extend([ 59 | ("identifier", "identifier", identifier.Identifier, False, None, False), 60 | ("period", "period", quantity.Quantity, False, None, True), 61 | ("specialPrecautionsForStorage", "specialPrecautionsForStorage", codeableconcept.CodeableConcept, True, None, False), 62 | ("type", "type", codeableconcept.CodeableConcept, False, None, True), 63 | ]) 64 | return js 65 | 66 | 67 | import sys 68 | try: 69 | from . import codeableconcept 70 | except ImportError: 71 | codeableconcept = sys.modules[__package__ + '.codeableconcept'] 72 | try: 73 | from . import identifier 74 | except ImportError: 75 | identifier = sys.modules[__package__ + '.identifier'] 76 | try: 77 | from . import quantity 78 | except ImportError: 79 | quantity = sys.modules[__package__ + '.quantity'] -------------------------------------------------------------------------------- /fhirbug/Fhir/Resources/flag.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Generated from FHIR 4.0.0-a53ec6ee1b (http://hl7.org/fhir/StructureDefinition/Flag) on 2019-01-25. 5 | # 2019, SMART Health IT. 6 | ## 7 | 8 | 9 | from . import domainresource 10 | 11 | class Flag(domainresource.DomainResource): 12 | """ Key information to flag to healthcare providers. 13 | 14 | Prospective warnings of potential issues when providing care to the 15 | patient. 16 | """ 17 | 18 | resource_type = "Flag" 19 | 20 | def __init__(self, jsondict=None, strict=True, **kwargs): 21 | """ Initialize all valid properties. 22 | 23 | :raises: FHIRValidationError on validation errors, unless strict is False 24 | :param dict jsondict: A JSON dictionary to use for initialization 25 | :param bool strict: If True (the default), invalid variables will raise a TypeError 26 | """ 27 | 28 | self.author = None 29 | """ Flag creator. 30 | Type `FHIRReference` (represented as `dict` in JSON). """ 31 | 32 | self.category = None 33 | """ Clinical, administrative, etc.. 34 | List of `CodeableConcept` items (represented as `dict` in JSON). """ 35 | 36 | self.code = None 37 | """ Coded or textual message to display to user. 38 | Type `CodeableConcept` (represented as `dict` in JSON). """ 39 | 40 | self.encounter = None 41 | """ Alert relevant during encounter. 42 | Type `FHIRReference` (represented as `dict` in JSON). """ 43 | 44 | self.identifier = None 45 | """ Business identifier. 46 | List of `Identifier` items (represented as `dict` in JSON). """ 47 | 48 | self.period = None 49 | """ Time period when flag is active. 50 | Type `Period` (represented as `dict` in JSON). """ 51 | 52 | self.status = None 53 | """ active | inactive | entered-in-error. 54 | Type `str`. """ 55 | 56 | self.subject = None 57 | """ Who/What is flag about?. 58 | Type `FHIRReference` (represented as `dict` in JSON). """ 59 | 60 | super(Flag, self).__init__(jsondict=jsondict, strict=strict, **kwargs) 61 | 62 | def elementProperties(self): 63 | js = super(Flag, self).elementProperties() 64 | js.extend([ 65 | ("author", "author", fhirreference.FHIRReference, False, None, False), 66 | ("category", "category", codeableconcept.CodeableConcept, True, None, False), 67 | ("code", "code", codeableconcept.CodeableConcept, False, None, True), 68 | ("encounter", "encounter", fhirreference.FHIRReference, False, None, False), 69 | ("identifier", "identifier", identifier.Identifier, True, None, False), 70 | ("period", "period", period.Period, False, None, False), 71 | ("status", "status", str, False, None, True), 72 | ("subject", "subject", fhirreference.FHIRReference, False, None, True), 73 | ]) 74 | return js 75 | 76 | 77 | import sys 78 | try: 79 | from . import codeableconcept 80 | except ImportError: 81 | codeableconcept = sys.modules[__package__ + '.codeableconcept'] 82 | try: 83 | from . import fhirreference 84 | except ImportError: 85 | fhirreference = sys.modules[__package__ + '.fhirreference'] 86 | try: 87 | from . import identifier 88 | except ImportError: 89 | identifier = sys.modules[__package__ + '.identifier'] 90 | try: 91 | from . import period 92 | except ImportError: 93 | period = sys.modules[__package__ + '.period'] -------------------------------------------------------------------------------- /fhirbug/Fhir/Resources/schedule.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Generated from FHIR 4.0.0-a53ec6ee1b (http://hl7.org/fhir/StructureDefinition/Schedule) on 2019-01-25. 5 | # 2019, SMART Health IT. 6 | ## 7 | 8 | 9 | from . import domainresource 10 | 11 | class Schedule(domainresource.DomainResource): 12 | """ A container for slots of time that may be available for booking 13 | appointments. 14 | """ 15 | 16 | resource_type = "Schedule" 17 | 18 | def __init__(self, jsondict=None, strict=True, **kwargs): 19 | """ Initialize all valid properties. 20 | 21 | :raises: FHIRValidationError on validation errors, unless strict is False 22 | :param dict jsondict: A JSON dictionary to use for initialization 23 | :param bool strict: If True (the default), invalid variables will raise a TypeError 24 | """ 25 | 26 | self.active = None 27 | """ Whether this schedule is in active use. 28 | Type `bool`. """ 29 | 30 | self.actor = None 31 | """ Resource(s) that availability information is being provided for. 32 | List of `FHIRReference` items (represented as `dict` in JSON). """ 33 | 34 | self.comment = None 35 | """ Comments on availability. 36 | Type `str`. """ 37 | 38 | self.identifier = None 39 | """ External Ids for this item. 40 | List of `Identifier` items (represented as `dict` in JSON). """ 41 | 42 | self.planningHorizon = None 43 | """ Period of time covered by schedule. 44 | Type `Period` (represented as `dict` in JSON). """ 45 | 46 | self.serviceCategory = None 47 | """ High-level category. 48 | List of `CodeableConcept` items (represented as `dict` in JSON). """ 49 | 50 | self.serviceType = None 51 | """ Specific service. 52 | List of `CodeableConcept` items (represented as `dict` in JSON). """ 53 | 54 | self.specialty = None 55 | """ Type of specialty needed. 56 | List of `CodeableConcept` items (represented as `dict` in JSON). """ 57 | 58 | super(Schedule, self).__init__(jsondict=jsondict, strict=strict, **kwargs) 59 | 60 | def elementProperties(self): 61 | js = super(Schedule, self).elementProperties() 62 | js.extend([ 63 | ("active", "active", bool, False, None, False), 64 | ("actor", "actor", fhirreference.FHIRReference, True, None, True), 65 | ("comment", "comment", str, False, None, False), 66 | ("identifier", "identifier", identifier.Identifier, True, None, False), 67 | ("planningHorizon", "planningHorizon", period.Period, False, None, False), 68 | ("serviceCategory", "serviceCategory", codeableconcept.CodeableConcept, True, None, False), 69 | ("serviceType", "serviceType", codeableconcept.CodeableConcept, True, None, False), 70 | ("specialty", "specialty", codeableconcept.CodeableConcept, True, None, False), 71 | ]) 72 | return js 73 | 74 | 75 | import sys 76 | try: 77 | from . import codeableconcept 78 | except ImportError: 79 | codeableconcept = sys.modules[__package__ + '.codeableconcept'] 80 | try: 81 | from . import fhirreference 82 | except ImportError: 83 | fhirreference = sys.modules[__package__ + '.fhirreference'] 84 | try: 85 | from . import identifier 86 | except ImportError: 87 | identifier = sys.modules[__package__ + '.identifier'] 88 | try: 89 | from . import period 90 | except ImportError: 91 | period = sys.modules[__package__ + '.period'] -------------------------------------------------------------------------------- /fhirbug/Fhir/Resources/researchsubject.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Generated from FHIR 4.0.0-a53ec6ee1b (http://hl7.org/fhir/StructureDefinition/ResearchSubject) on 2019-01-25. 5 | # 2019, SMART Health IT. 6 | ## 7 | 8 | 9 | from . import domainresource 10 | 11 | class ResearchSubject(domainresource.DomainResource): 12 | """ Physical entity which is the primary unit of interest in the study. 13 | 14 | A physical entity which is the primary unit of operational and/or 15 | administrative interest in a study. 16 | """ 17 | 18 | resource_type = "ResearchSubject" 19 | 20 | def __init__(self, jsondict=None, strict=True, **kwargs): 21 | """ Initialize all valid properties. 22 | 23 | :raises: FHIRValidationError on validation errors, unless strict is False 24 | :param dict jsondict: A JSON dictionary to use for initialization 25 | :param bool strict: If True (the default), invalid variables will raise a TypeError 26 | """ 27 | 28 | self.actualArm = None 29 | """ What path was followed. 30 | Type `str`. """ 31 | 32 | self.assignedArm = None 33 | """ What path should be followed. 34 | Type `str`. """ 35 | 36 | self.consent = None 37 | """ Agreement to participate in study. 38 | Type `FHIRReference` (represented as `dict` in JSON). """ 39 | 40 | self.identifier = None 41 | """ Business Identifier for research subject in a study. 42 | List of `Identifier` items (represented as `dict` in JSON). """ 43 | 44 | self.individual = None 45 | """ Who is part of study. 46 | Type `FHIRReference` (represented as `dict` in JSON). """ 47 | 48 | self.period = None 49 | """ Start and end of participation. 50 | Type `Period` (represented as `dict` in JSON). """ 51 | 52 | self.status = None 53 | """ candidate | eligible | follow-up | ineligible | not-registered | 54 | off-study | on-study | on-study-intervention | on-study-observation 55 | | pending-on-study | potential-candidate | screening | withdrawn. 56 | Type `str`. """ 57 | 58 | self.study = None 59 | """ Study subject is part of. 60 | Type `FHIRReference` (represented as `dict` in JSON). """ 61 | 62 | super(ResearchSubject, self).__init__(jsondict=jsondict, strict=strict, **kwargs) 63 | 64 | def elementProperties(self): 65 | js = super(ResearchSubject, self).elementProperties() 66 | js.extend([ 67 | ("actualArm", "actualArm", str, False, None, False), 68 | ("assignedArm", "assignedArm", str, False, None, False), 69 | ("consent", "consent", fhirreference.FHIRReference, False, None, False), 70 | ("identifier", "identifier", identifier.Identifier, True, None, False), 71 | ("individual", "individual", fhirreference.FHIRReference, False, None, True), 72 | ("period", "period", period.Period, False, None, False), 73 | ("status", "status", str, False, None, True), 74 | ("study", "study", fhirreference.FHIRReference, False, None, True), 75 | ]) 76 | return js 77 | 78 | 79 | import sys 80 | try: 81 | from . import fhirreference 82 | except ImportError: 83 | fhirreference = sys.modules[__package__ + '.fhirreference'] 84 | try: 85 | from . import identifier 86 | except ImportError: 87 | identifier = sys.modules[__package__ + '.identifier'] 88 | try: 89 | from . import period 90 | except ImportError: 91 | period = sys.modules[__package__ + '.period'] -------------------------------------------------------------------------------- /fhirbug/Fhir/Resources/bodystructure.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Generated from FHIR 4.0.0-a53ec6ee1b (http://hl7.org/fhir/StructureDefinition/BodyStructure) on 2019-01-25. 5 | # 2019, SMART Health IT. 6 | ## 7 | 8 | 9 | from . import domainresource 10 | 11 | class BodyStructure(domainresource.DomainResource): 12 | """ Specific and identified anatomical structure. 13 | 14 | Record details about an anatomical structure. This resource may be used 15 | when a coded concept does not provide the necessary detail needed for the 16 | use case. 17 | """ 18 | 19 | resource_type = "BodyStructure" 20 | 21 | def __init__(self, jsondict=None, strict=True, **kwargs): 22 | """ Initialize all valid properties. 23 | 24 | :raises: FHIRValidationError on validation errors, unless strict is False 25 | :param dict jsondict: A JSON dictionary to use for initialization 26 | :param bool strict: If True (the default), invalid variables will raise a TypeError 27 | """ 28 | 29 | self.active = None 30 | """ Whether this record is in active use. 31 | Type `bool`. """ 32 | 33 | self.description = None 34 | """ Text description. 35 | Type `str`. """ 36 | 37 | self.identifier = None 38 | """ Bodystructure identifier. 39 | List of `Identifier` items (represented as `dict` in JSON). """ 40 | 41 | self.image = None 42 | """ Attached images. 43 | List of `Attachment` items (represented as `dict` in JSON). """ 44 | 45 | self.location = None 46 | """ Body site. 47 | Type `CodeableConcept` (represented as `dict` in JSON). """ 48 | 49 | self.locationQualifier = None 50 | """ Body site modifier. 51 | List of `CodeableConcept` items (represented as `dict` in JSON). """ 52 | 53 | self.morphology = None 54 | """ Kind of Structure. 55 | Type `CodeableConcept` (represented as `dict` in JSON). """ 56 | 57 | self.patient = None 58 | """ Who this is about. 59 | Type `FHIRReference` (represented as `dict` in JSON). """ 60 | 61 | super(BodyStructure, self).__init__(jsondict=jsondict, strict=strict, **kwargs) 62 | 63 | def elementProperties(self): 64 | js = super(BodyStructure, self).elementProperties() 65 | js.extend([ 66 | ("active", "active", bool, False, None, False), 67 | ("description", "description", str, False, None, False), 68 | ("identifier", "identifier", identifier.Identifier, True, None, False), 69 | ("image", "image", attachment.Attachment, True, None, False), 70 | ("location", "location", codeableconcept.CodeableConcept, False, None, False), 71 | ("locationQualifier", "locationQualifier", codeableconcept.CodeableConcept, True, None, False), 72 | ("morphology", "morphology", codeableconcept.CodeableConcept, False, None, False), 73 | ("patient", "patient", fhirreference.FHIRReference, False, None, True), 74 | ]) 75 | return js 76 | 77 | 78 | import sys 79 | try: 80 | from . import attachment 81 | except ImportError: 82 | attachment = sys.modules[__package__ + '.attachment'] 83 | try: 84 | from . import codeableconcept 85 | except ImportError: 86 | codeableconcept = sys.modules[__package__ + '.codeableconcept'] 87 | try: 88 | from . import fhirreference 89 | except ImportError: 90 | fhirreference = sys.modules[__package__ + '.fhirreference'] 91 | try: 92 | from . import identifier 93 | except ImportError: 94 | identifier = sys.modules[__package__ + '.identifier'] -------------------------------------------------------------------------------- /tests/test_backends.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | # from datetime import date, datetime 3 | # from types import SimpleNamespace 4 | from unittest.mock import Mock, patch, MagicMock 5 | 6 | # from fhirbug.exceptions import QueryValidationError 7 | from fhirbug.db.backends.SQLAlchemy.pagination import paginate as paginate_sqla 8 | from fhirbug.db.backends.DjangoORM.pagination import paginate as paginate_django 9 | from fhirbug.db.backends.pymodm.pagination import paginate as paginate_pymodm 10 | 11 | 12 | class TestSQLAlchemyPaginate(unittest.TestCase): 13 | # def setUp(self): 14 | def test_value_checks(self): 15 | with self.assertRaises(AttributeError) as e: 16 | paginate_sqla('query', -1, 1) 17 | self.assertEqual(e.exception.args[0], "page needs to be >= 1") 18 | with self.assertRaises(AttributeError) as e: 19 | paginate_sqla('query', 1, -1) 20 | self.assertEqual(e.exception.args[0], "page_size needs to be >= 1") 21 | 22 | @patch('fhirbug.db.backends.SQLAlchemy.pagination.Page') 23 | def test_paginate(self, PageMock): 24 | query = Mock() 25 | ret = paginate_sqla(query, 4, 10) 26 | query.limit.assert_called_with(10) 27 | query.limit().offset.assert_called_with((4-1)*10) 28 | query.limit().offset().all.assert_called() 29 | 30 | query.order_by.assert_called_with(None) 31 | query.order_by().count.assert_called() 32 | PageMock.assert_called_with(query.limit().offset().all(), 4, 10, query.order_by().count()) 33 | self.assertEqual(ret, PageMock()) 34 | 35 | 36 | class TestDjangoORMPaginate(unittest.TestCase): 37 | # def setUp(self): 38 | def test_value_checks(self): 39 | with self.assertRaises(AttributeError) as e: 40 | paginate_django('query', -1, 1) 41 | self.assertEqual(e.exception.args[0], "page needs to be >= 1") 42 | with self.assertRaises(AttributeError) as e: 43 | paginate_django('query', 1, -1) 44 | self.assertEqual(e.exception.args[0], "page_size needs to be >= 1") 45 | 46 | @patch('fhirbug.db.backends.DjangoORM.pagination.Paginator') 47 | @patch('fhirbug.db.backends.DjangoORM.pagination.Page') 48 | def test_paginate(self, PageMock, PaginatorMock): 49 | query = Mock() 50 | ret = paginate_django(query, 4, 10) 51 | query.all.assert_called() 52 | PaginatorMock.assert_called_with(query.all(), 10) 53 | PaginatorMock().get_page.assert_called_with(4) 54 | query.count.assert_called() 55 | 56 | PageMock.assert_called_with(PaginatorMock().get_page(), 4, 10, query.count()) 57 | self.assertEqual(ret, PageMock()) 58 | 59 | 60 | class TestPyMODMPaginate(unittest.TestCase): 61 | # def setUp(self): 62 | def test_value_checks(self): 63 | with self.assertRaises(AttributeError) as e: 64 | paginate_pymodm('query', -1, 1) 65 | self.assertEqual(e.exception.args[0], "page needs to be >= 1") 66 | with self.assertRaises(AttributeError) as e: 67 | paginate_pymodm('query', 1, -1) 68 | self.assertEqual(e.exception.args[0], "page_size needs to be >= 1") 69 | 70 | @patch('fhirbug.db.backends.pymodm.pagination.Page') 71 | def test_paginate(self, PageMock): 72 | query = MagicMock() 73 | ret = paginate_pymodm(query, 4, 10) 74 | 75 | query.limit.assert_called_with(10) 76 | query.limit().skip.assert_called_with((4-1)*10) 77 | query.limit().skip().all.assert_called() 78 | query.count.assert_called() 79 | 80 | PageMock.assert_called_with(list(query.limit().skip().all()), 4, 10, query.count()) 81 | self.assertEqual(ret, PageMock()) 82 | -------------------------------------------------------------------------------- /fhirbug/Fhir/Resources/appointmentresponse.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Generated from FHIR 4.0.0-a53ec6ee1b (http://hl7.org/fhir/StructureDefinition/AppointmentResponse) on 2019-01-25. 5 | # 2019, SMART Health IT. 6 | ## 7 | 8 | 9 | from . import domainresource 10 | 11 | class AppointmentResponse(domainresource.DomainResource): 12 | """ A reply to an appointment request for a patient and/or practitioner(s), 13 | such as a confirmation or rejection. 14 | """ 15 | 16 | resource_type = "AppointmentResponse" 17 | 18 | def __init__(self, jsondict=None, strict=True, **kwargs): 19 | """ Initialize all valid properties. 20 | 21 | :raises: FHIRValidationError on validation errors, unless strict is False 22 | :param dict jsondict: A JSON dictionary to use for initialization 23 | :param bool strict: If True (the default), invalid variables will raise a TypeError 24 | """ 25 | 26 | self.actor = None 27 | """ Person, Location, HealthcareService, or Device. 28 | Type `FHIRReference` (represented as `dict` in JSON). """ 29 | 30 | self.appointment = None 31 | """ Appointment this response relates to. 32 | Type `FHIRReference` (represented as `dict` in JSON). """ 33 | 34 | self.comment = None 35 | """ Additional comments. 36 | Type `str`. """ 37 | 38 | self.end = None 39 | """ Time from appointment, or requested new end time. 40 | Type `FHIRDate` (represented as `str` in JSON). """ 41 | 42 | self.identifier = None 43 | """ External Ids for this item. 44 | List of `Identifier` items (represented as `dict` in JSON). """ 45 | 46 | self.participantStatus = None 47 | """ accepted | declined | tentative | in-process | completed | needs- 48 | action | entered-in-error. 49 | Type `str`. """ 50 | 51 | self.participantType = None 52 | """ Role of participant in the appointment. 53 | List of `CodeableConcept` items (represented as `dict` in JSON). """ 54 | 55 | self.start = None 56 | """ Time from appointment, or requested new start time. 57 | Type `FHIRDate` (represented as `str` in JSON). """ 58 | 59 | super(AppointmentResponse, self).__init__(jsondict=jsondict, strict=strict, **kwargs) 60 | 61 | def elementProperties(self): 62 | js = super(AppointmentResponse, self).elementProperties() 63 | js.extend([ 64 | ("actor", "actor", fhirreference.FHIRReference, False, None, False), 65 | ("appointment", "appointment", fhirreference.FHIRReference, False, None, True), 66 | ("comment", "comment", str, False, None, False), 67 | ("end", "end", fhirdate.FHIRDate, False, None, False), 68 | ("identifier", "identifier", identifier.Identifier, True, None, False), 69 | ("participantStatus", "participantStatus", str, False, None, True), 70 | ("participantType", "participantType", codeableconcept.CodeableConcept, True, None, False), 71 | ("start", "start", fhirdate.FHIRDate, False, None, False), 72 | ]) 73 | return js 74 | 75 | 76 | import sys 77 | try: 78 | from . import codeableconcept 79 | except ImportError: 80 | codeableconcept = sys.modules[__package__ + '.codeableconcept'] 81 | try: 82 | from . import fhirdate 83 | except ImportError: 84 | fhirdate = sys.modules[__package__ + '.fhirdate'] 85 | try: 86 | from . import fhirreference 87 | except ImportError: 88 | fhirreference = sys.modules[__package__ + '.fhirreference'] 89 | try: 90 | from . import identifier 91 | except ImportError: 92 | identifier = sys.modules[__package__ + '.identifier'] -------------------------------------------------------------------------------- /fhirbug/Fhir/Resources/triggerdefinition.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Generated from FHIR 4.0.0-a53ec6ee1b (http://hl7.org/fhir/StructureDefinition/TriggerDefinition) on 2019-01-25. 5 | # 2019, SMART Health IT. 6 | ## 7 | 8 | 9 | from . import element 10 | 11 | class TriggerDefinition(element.Element): 12 | """ Defines an expected trigger for a module. 13 | 14 | A description of a triggering event. Triggering events can be named events, 15 | data events, or periodic, as determined by the type element. 16 | """ 17 | 18 | resource_type = "TriggerDefinition" 19 | 20 | def __init__(self, jsondict=None, strict=True, **kwargs): 21 | """ Initialize all valid properties. 22 | 23 | :raises: FHIRValidationError on validation errors, unless strict is False 24 | :param dict jsondict: A JSON dictionary to use for initialization 25 | :param bool strict: If True (the default), invalid variables will raise a TypeError 26 | """ 27 | 28 | self.condition = None 29 | """ Whether the event triggers (boolean expression). 30 | Type `Expression` (represented as `dict` in JSON). """ 31 | 32 | self.data = None 33 | """ Triggering data of the event (multiple = 'and'). 34 | List of `DataRequirement` items (represented as `dict` in JSON). """ 35 | 36 | self.name = None 37 | """ Name or URI that identifies the event. 38 | Type `str`. """ 39 | 40 | self.timingDate = None 41 | """ Timing of the event. 42 | Type `FHIRDate` (represented as `str` in JSON). """ 43 | 44 | self.timingDateTime = None 45 | """ Timing of the event. 46 | Type `FHIRDate` (represented as `str` in JSON). """ 47 | 48 | self.timingReference = None 49 | """ Timing of the event. 50 | Type `FHIRReference` (represented as `dict` in JSON). """ 51 | 52 | self.timingTiming = None 53 | """ Timing of the event. 54 | Type `Timing` (represented as `dict` in JSON). """ 55 | 56 | self.type = None 57 | """ named-event | periodic | data-changed | data-added | data-modified 58 | | data-removed | data-accessed | data-access-ended. 59 | Type `str`. """ 60 | 61 | super(TriggerDefinition, self).__init__(jsondict=jsondict, strict=strict, **kwargs) 62 | 63 | def elementProperties(self): 64 | js = super(TriggerDefinition, self).elementProperties() 65 | js.extend([ 66 | ("condition", "condition", expression.Expression, False, None, False), 67 | ("data", "data", datarequirement.DataRequirement, True, None, False), 68 | ("name", "name", str, False, None, False), 69 | ("timingDate", "timingDate", fhirdate.FHIRDate, False, "timing", False), 70 | ("timingDateTime", "timingDateTime", fhirdate.FHIRDate, False, "timing", False), 71 | ("timingReference", "timingReference", fhirreference.FHIRReference, False, "timing", False), 72 | ("timingTiming", "timingTiming", timing.Timing, False, "timing", False), 73 | ("type", "type", str, False, None, True), 74 | ]) 75 | return js 76 | 77 | 78 | import sys 79 | try: 80 | from . import datarequirement 81 | except ImportError: 82 | datarequirement = sys.modules[__package__ + '.datarequirement'] 83 | try: 84 | from . import expression 85 | except ImportError: 86 | expression = sys.modules[__package__ + '.expression'] 87 | try: 88 | from . import fhirdate 89 | except ImportError: 90 | fhirdate = sys.modules[__package__ + '.fhirdate'] 91 | try: 92 | from . import fhirreference 93 | except ImportError: 94 | fhirreference = sys.modules[__package__ + '.fhirreference'] 95 | try: 96 | from . import timing 97 | except ImportError: 98 | timing = sys.modules[__package__ + '.timing'] -------------------------------------------------------------------------------- /fhirbug/Fhir/Resources/medicinalproductmanufactured.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Generated from FHIR 4.0.0-a53ec6ee1b (http://hl7.org/fhir/StructureDefinition/MedicinalProductManufactured) on 2019-01-25. 5 | # 2019, SMART Health IT. 6 | ## 7 | 8 | 9 | from . import domainresource 10 | 11 | class MedicinalProductManufactured(domainresource.DomainResource): 12 | """ The manufactured item as contained in the packaged medicinal product. 13 | """ 14 | 15 | resource_type = "MedicinalProductManufactured" 16 | 17 | def __init__(self, jsondict=None, strict=True, **kwargs): 18 | """ Initialize all valid properties. 19 | 20 | :raises: FHIRValidationError on validation errors, unless strict is False 21 | :param dict jsondict: A JSON dictionary to use for initialization 22 | :param bool strict: If True (the default), invalid variables will raise a TypeError 23 | """ 24 | 25 | self.ingredient = None 26 | """ Ingredient. 27 | List of `FHIRReference` items (represented as `dict` in JSON). """ 28 | 29 | self.manufacturedDoseForm = None 30 | """ Dose form as manufactured and before any transformation into the 31 | pharmaceutical product. 32 | Type `CodeableConcept` (represented as `dict` in JSON). """ 33 | 34 | self.manufacturer = None 35 | """ Manufacturer of the item (Note that this should be named 36 | "manufacturer" but it currently causes technical issues). 37 | List of `FHIRReference` items (represented as `dict` in JSON). """ 38 | 39 | self.otherCharacteristics = None 40 | """ Other codeable characteristics. 41 | List of `CodeableConcept` items (represented as `dict` in JSON). """ 42 | 43 | self.physicalCharacteristics = None 44 | """ Dimensions, color etc.. 45 | Type `ProdCharacteristic` (represented as `dict` in JSON). """ 46 | 47 | self.quantity = None 48 | """ The quantity or "count number" of the manufactured item. 49 | Type `Quantity` (represented as `dict` in JSON). """ 50 | 51 | self.unitOfPresentation = None 52 | """ The “real world” units in which the quantity of the manufactured 53 | item is described. 54 | Type `CodeableConcept` (represented as `dict` in JSON). """ 55 | 56 | super(MedicinalProductManufactured, self).__init__(jsondict=jsondict, strict=strict, **kwargs) 57 | 58 | def elementProperties(self): 59 | js = super(MedicinalProductManufactured, self).elementProperties() 60 | js.extend([ 61 | ("ingredient", "ingredient", fhirreference.FHIRReference, True, None, False), 62 | ("manufacturedDoseForm", "manufacturedDoseForm", codeableconcept.CodeableConcept, False, None, True), 63 | ("manufacturer", "manufacturer", fhirreference.FHIRReference, True, None, False), 64 | ("otherCharacteristics", "otherCharacteristics", codeableconcept.CodeableConcept, True, None, False), 65 | ("physicalCharacteristics", "physicalCharacteristics", prodcharacteristic.ProdCharacteristic, False, None, False), 66 | ("quantity", "quantity", quantity.Quantity, False, None, True), 67 | ("unitOfPresentation", "unitOfPresentation", codeableconcept.CodeableConcept, False, None, False), 68 | ]) 69 | return js 70 | 71 | 72 | import sys 73 | try: 74 | from . import codeableconcept 75 | except ImportError: 76 | codeableconcept = sys.modules[__package__ + '.codeableconcept'] 77 | try: 78 | from . import fhirreference 79 | except ImportError: 80 | fhirreference = sys.modules[__package__ + '.fhirreference'] 81 | try: 82 | from . import prodcharacteristic 83 | except ImportError: 84 | prodcharacteristic = sys.modules[__package__ + '.prodcharacteristic'] 85 | try: 86 | from . import quantity 87 | except ImportError: 88 | quantity = sys.modules[__package__ + '.quantity'] -------------------------------------------------------------------------------- /fhirbug/Fhir/Resources/operationoutcome.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Generated from FHIR 4.0.0-a53ec6ee1b (http://hl7.org/fhir/StructureDefinition/OperationOutcome) on 2019-01-25. 5 | # 2019, SMART Health IT. 6 | ## 7 | 8 | 9 | from . import domainresource 10 | 11 | class OperationOutcome(domainresource.DomainResource): 12 | """ Information about the success/failure of an action. 13 | 14 | A collection of error, warning, or information messages that result from a 15 | system action. 16 | """ 17 | 18 | resource_type = "OperationOutcome" 19 | 20 | def __init__(self, jsondict=None, strict=True, **kwargs): 21 | """ Initialize all valid properties. 22 | 23 | :raises: FHIRValidationError on validation errors, unless strict is False 24 | :param dict jsondict: A JSON dictionary to use for initialization 25 | :param bool strict: If True (the default), invalid variables will raise a TypeError 26 | """ 27 | 28 | self.issue = None 29 | """ A single issue associated with the action. 30 | List of `OperationOutcomeIssue` items (represented as `dict` in JSON). """ 31 | 32 | super(OperationOutcome, self).__init__(jsondict=jsondict, strict=strict, **kwargs) 33 | 34 | def elementProperties(self): 35 | js = super(OperationOutcome, self).elementProperties() 36 | js.extend([ 37 | ("issue", "issue", OperationOutcomeIssue, True, None, True), 38 | ]) 39 | return js 40 | 41 | 42 | from . import backboneelement 43 | 44 | class OperationOutcomeIssue(backboneelement.BackboneElement): 45 | """ A single issue associated with the action. 46 | 47 | An error, warning, or information message that results from a system 48 | action. 49 | """ 50 | 51 | resource_type = "OperationOutcomeIssue" 52 | 53 | def __init__(self, jsondict=None, strict=True, **kwargs): 54 | """ Initialize all valid properties. 55 | 56 | :raises: FHIRValidationError on validation errors, unless strict is False 57 | :param dict jsondict: A JSON dictionary to use for initialization 58 | :param bool strict: If True (the default), invalid variables will raise a TypeError 59 | """ 60 | 61 | self.code = None 62 | """ Error or warning code. 63 | Type `str`. """ 64 | 65 | self.details = None 66 | """ Additional details about the error. 67 | Type `CodeableConcept` (represented as `dict` in JSON). """ 68 | 69 | self.diagnostics = None 70 | """ Additional diagnostic information about the issue. 71 | Type `str`. """ 72 | 73 | self.expression = None 74 | """ FHIRPath of element(s) related to issue. 75 | List of `str` items. """ 76 | 77 | self.location = None 78 | """ Deprecated: Path of element(s) related to issue. 79 | List of `str` items. """ 80 | 81 | self.severity = None 82 | """ fatal | error | warning | information. 83 | Type `str`. """ 84 | 85 | super(OperationOutcomeIssue, self).__init__(jsondict=jsondict, strict=strict, **kwargs) 86 | 87 | def elementProperties(self): 88 | js = super(OperationOutcomeIssue, self).elementProperties() 89 | js.extend([ 90 | ("code", "code", str, False, None, True), 91 | ("details", "details", codeableconcept.CodeableConcept, False, None, False), 92 | ("diagnostics", "diagnostics", str, False, None, False), 93 | ("expression", "expression", str, True, None, False), 94 | ("location", "location", str, True, None, False), 95 | ("severity", "severity", str, False, None, True), 96 | ]) 97 | return js 98 | 99 | 100 | import sys 101 | try: 102 | from . import codeableconcept 103 | except ImportError: 104 | codeableconcept = sys.modules[__package__ + '.codeableconcept'] -------------------------------------------------------------------------------- /fhirbug/Fhir/base/fhirreference.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Subclassing FHIR's reference to add resolving capabilities 5 | 6 | import logging 7 | from . import reference 8 | 9 | logger = logging.getLogger(__name__) 10 | 11 | 12 | class FHIRReference(reference.Reference): 13 | """ Subclassing FHIR's `Reference` resource to add resolving capabilities. 14 | """ 15 | 16 | def resolved(self, klass): 17 | """ Resolves the reference and caches the result, returning instance(s) 18 | of the referenced classes. 19 | 20 | :param klass: The expected class of the resource 21 | :returns: An instance (or list thereof) of the resolved reference if 22 | dereferencing was successful, `None` otherwise 23 | """ 24 | owning_resource = self.owningResource() 25 | if owning_resource is None: 26 | raise Exception("Cannot resolve reference without having an owner (which must be a `DomainResource`)") 27 | if klass is None: 28 | raise Exception("Cannot resolve reference without knowing the class") 29 | 30 | refid = self.processedReferenceIdentifier() 31 | if not refid: 32 | logger.warning("No `reference` set, cannot resolve") 33 | return None 34 | 35 | # already resolved and cached? 36 | resolved = owning_resource.resolvedReference(refid) 37 | if resolved is not None: 38 | if isinstance(resolved, klass): 39 | return resolved 40 | logger.warning("Referenced resource {} is not a {} but a {}".format(refid, klass, resolved.__class__)) 41 | return None 42 | 43 | # not yet resolved, see if it's a contained resource 44 | if owning_resource.contained is not None: 45 | for contained in owning_resource.contained: 46 | if contained.id == refid: 47 | owning_resource.didResolveReference(refid, contained) 48 | if isinstance(contained, klass): 49 | return contained 50 | logger.warning("Contained resource {} is not a {} but a {}".format(refid, klass, contained.__class__)) 51 | return None 52 | 53 | # are we in a bundle? 54 | ref_is_relative = '://' not in self.reference and 'urn:' != self.reference[:4] 55 | bundle = self.owningBundle() 56 | while bundle is not None: 57 | if bundle.entry is not None: 58 | fullUrl = self.reference 59 | if ref_is_relative: 60 | base = bundle.server.base_uri if bundle.server else '' 61 | fullUrl = base + self.reference 62 | 63 | for entry in bundle.entry: 64 | if entry.fullUrl == fullUrl: 65 | found = entry.resource 66 | if isinstance(found, klass): 67 | return found 68 | logger.warning("Bundled resource {} is not a {} but a {}".format(refid, klass, found.__class__)) 69 | return None 70 | bundle = bundle.owningBundle() 71 | 72 | # relative references, use the same server 73 | server = None 74 | if ref_is_relative: 75 | server = owning_resource.server if owning_resource else None 76 | 77 | # TODO: instantiate server for absolute resource 78 | if server is None: 79 | logger.warning("Not implemented: resolving absolute reference to resource {}" 80 | .format(self.reference)) 81 | return None 82 | 83 | # fetch remote resource; unable to verify klass since we use klass.read_from() 84 | relative = klass.read_from(self.reference, server) 85 | owning_resource.didResolveReference(refid, relative) 86 | return relative 87 | 88 | def processedReferenceIdentifier(self): 89 | """ Normalizes the reference-id. 90 | """ 91 | if self.reference and '#' == self.reference[0]: 92 | return self.reference[1:] 93 | return self.reference 94 | 95 | -------------------------------------------------------------------------------- /fhirbug/Fhir/Resources/fhirreference.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Subclassing FHIR's reference to add resolving capabilities 5 | 6 | import logging 7 | from . import reference 8 | 9 | logger = logging.getLogger(__name__) 10 | 11 | 12 | class FHIRReference(reference.Reference): 13 | """ Subclassing FHIR's `Reference` resource to add resolving capabilities. 14 | """ 15 | 16 | def resolved(self, klass): 17 | """ Resolves the reference and caches the result, returning instance(s) 18 | of the referenced classes. 19 | 20 | :param klass: The expected class of the resource 21 | :returns: An instance (or list thereof) of the resolved reference if 22 | dereferencing was successful, `None` otherwise 23 | """ 24 | owning_resource = self.owningResource() 25 | if owning_resource is None: 26 | raise Exception("Cannot resolve reference without having an owner (which must be a `DomainResource`)") 27 | if klass is None: 28 | raise Exception("Cannot resolve reference without knowing the class") 29 | 30 | refid = self.processedReferenceIdentifier() 31 | if not refid: 32 | logger.warning("No `reference` set, cannot resolve") 33 | return None 34 | 35 | # already resolved and cached? 36 | resolved = owning_resource.resolvedReference(refid) 37 | if resolved is not None: 38 | if isinstance(resolved, klass): 39 | return resolved 40 | logger.warning("Referenced resource {} is not a {} but a {}".format(refid, klass, resolved.__class__)) 41 | return None 42 | 43 | # not yet resolved, see if it's a contained resource 44 | if owning_resource.contained is not None: 45 | for contained in owning_resource.contained: 46 | if contained.id == refid: 47 | owning_resource.didResolveReference(refid, contained) 48 | if isinstance(contained, klass): 49 | return contained 50 | logger.warning("Contained resource {} is not a {} but a {}".format(refid, klass, contained.__class__)) 51 | return None 52 | 53 | # are we in a bundle? 54 | ref_is_relative = '://' not in self.reference and 'urn:' != self.reference[:4] 55 | bundle = self.owningBundle() 56 | while bundle is not None: 57 | if bundle.entry is not None: 58 | fullUrl = self.reference 59 | if ref_is_relative: 60 | base = bundle.server.base_uri if bundle.server else '' 61 | fullUrl = base + self.reference 62 | 63 | for entry in bundle.entry: 64 | if entry.fullUrl == fullUrl: 65 | found = entry.resource 66 | if isinstance(found, klass): 67 | return found 68 | logger.warning("Bundled resource {} is not a {} but a {}".format(refid, klass, found.__class__)) 69 | return None 70 | bundle = bundle.owningBundle() 71 | 72 | # relative references, use the same server 73 | server = None 74 | if ref_is_relative: 75 | server = owning_resource.server if owning_resource else None 76 | 77 | # TODO: instantiate server for absolute resource 78 | if server is None: 79 | logger.warning("Not implemented: resolving absolute reference to resource {}" 80 | .format(self.reference)) 81 | return None 82 | 83 | # fetch remote resource; unable to verify klass since we use klass.read_from() 84 | relative = klass.read_from(self.reference, server) 85 | owning_resource.didResolveReference(refid, relative) 86 | return relative 87 | 88 | def processedReferenceIdentifier(self): 89 | """ Normalizes the reference-id. 90 | """ 91 | if self.reference and '#' == self.reference[0]: 92 | return self.reference[1:] 93 | return self.reference 94 | 95 | -------------------------------------------------------------------------------- /docs/overview/logging.rst: -------------------------------------------------------------------------------- 1 | Logging 2 | ------- 3 | 4 | Fhirbug's :mod:`RequestHandlers ` all have a 5 | method called ``log_request`` that is called whenever a request is done being proccessed 6 | with several information about the request. 7 | 8 | By default, this method returns an :class:`AuditEvent ` FHIR resource instance populated 9 | with available information about the request. 10 | 11 | 12 | Enhancing or persisting the default handler 13 | ___________________________________________________ 14 | 15 | Enhancing the generated AuditEvents with extra information about the request 16 | and Persisiting them is pretty simple. Just use custom :mod:`RequestHandlers ` and override the ``log_request`` method: 17 | 18 | :: 19 | 20 | from fhirbug.Fhir.resources import AuditEventEntity 21 | from fhirbug.config import import_models 22 | 23 | class EnhancedLoggingMixin: 24 | def log_request(self, *args, **kwargs): 25 | audit_event = super(EnhancedLoggingMixin, self).log_request(*args, **kwargs) 26 | 27 | context = kwargs["query"].context 28 | user = context.user 29 | # We populate the entity field with info about the user 30 | audit_event.entity = [ 31 | AuditEventEntity({ 32 | "type": {"display": "Person"}, 33 | "name": user.username, 34 | "description": user.userid, 35 | }) 36 | ] 37 | return audit_event 38 | 39 | 40 | class PersistentLoggingMixin: 41 | def log_request(self, *args, **kwargs): 42 | audit_event = super(PersistentLoggingMixin, self).log_request(*args, **kwargs) 43 | models = import_models() 44 | AuditEvent = getattr(models, 'AuditEvent') 45 | audit_event_model = AuditEvent.create_from_resource(audit_event) 46 | return audit_event 47 | 48 | # Create the handler 49 | class CustomGetRequestHandler( 50 | PersistentLoggingMixin, EnhancedLoggingMixin, GetRequestHandler 51 | ): 52 | pass 53 | 54 | .. note:: In order to have access to the user instance we assume you have passed 55 | a query context to the request handler's handle method containing 56 | the necessary info 57 | 58 | .. note:: Note that the order in which we pass the mixins to the custom handler class 59 | is important. Python applies mixins from right to left, meaning 60 | ``PersistentLoggingMixin``'s ``super()`` method will call 61 | ``EnhancedLoggingMixin``'s ``log_request`` and ``EnhancedLoggingMixin``'s 62 | ``super()`` method will call ``GetRequestHandler``'s 63 | 64 | 65 | So, we expect the AuditEvent that is persisted by the 66 | ``PersistentLoggingMixin`` to contain information about the user because 67 | it is comes before ``EnhancedLoggingMixin`` in the class definition 68 | 69 | 70 | Creating a custom log handler 71 | ___________________________________________________ 72 | 73 | If you don't want to use fhirbug's default log handling and want to implement 74 | something your self, the process is pretty much the same. You implement your own 75 | ``log_request`` method and process the information that is passed to it by 76 | fhirbug any way you want. Essentially the only difference with the examples above 77 | is that you do not call ``super()`` inside your custom log function. 78 | 79 | The signature of the ``log_request`` function is the following: 80 | 81 | .. automethod:: fhirbug.server.requesthandlers.AbstractRequestHandler.log_request(self, url, query, status, method, resource=None, OperationOutcome=None, request_body=None, time=datetime.now()) 82 | :noindex: 83 | 84 | Here's an example where we use python's built-in logging module: 85 | 86 | :: 87 | 88 | from datetme import datetime 89 | from logging import getLogger 90 | 91 | logger = getLogger(__name__) 92 | 93 | class CustomGetRequestHandler(GetRequestHandler): 94 | def log_request(self, url, status, method, *args, **kwargs): 95 | logger.info("%s: %s %s %s" % (datetime.now(), method, url, status)) 96 | -------------------------------------------------------------------------------- /fhirbug/Fhir/Resources/marketingstatus.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Generated from FHIR 4.0.0-a53ec6ee1b (http://hl7.org/fhir/StructureDefinition/MarketingStatus) on 2019-01-25. 5 | # 2019, SMART Health IT. 6 | ## 7 | 8 | 9 | from . import backboneelement 10 | 11 | class MarketingStatus(backboneelement.BackboneElement): 12 | """ The marketing status describes the date when a medicinal product is 13 | actually put on the market or the date as of which it is no longer 14 | available. 15 | """ 16 | 17 | resource_type = "MarketingStatus" 18 | 19 | def __init__(self, jsondict=None, strict=True, **kwargs): 20 | """ Initialize all valid properties. 21 | 22 | :raises: FHIRValidationError on validation errors, unless strict is False 23 | :param dict jsondict: A JSON dictionary to use for initialization 24 | :param bool strict: If True (the default), invalid variables will raise a TypeError 25 | """ 26 | 27 | self.country = None 28 | """ The country in which the marketing authorisation has been granted 29 | shall be specified It should be specified using the ISO 3166 ‑ 1 30 | alpha-2 code elements. 31 | Type `CodeableConcept` (represented as `dict` in JSON). """ 32 | 33 | self.dateRange = None 34 | """ The date when the Medicinal Product is placed on the market by the 35 | Marketing Authorisation Holder (or where applicable, the 36 | manufacturer/distributor) in a country and/or jurisdiction shall be 37 | provided A complete date consisting of day, month and year shall be 38 | specified using the ISO 8601 date format NOTE “Placed on the 39 | market” refers to the release of the Medicinal Product into the 40 | distribution chain. 41 | Type `Period` (represented as `dict` in JSON). """ 42 | 43 | self.jurisdiction = None 44 | """ Where a Medicines Regulatory Agency has granted a marketing 45 | authorisation for which specific provisions within a jurisdiction 46 | apply, the jurisdiction can be specified using an appropriate 47 | controlled terminology The controlled term and the controlled term 48 | identifier shall be specified. 49 | Type `CodeableConcept` (represented as `dict` in JSON). """ 50 | 51 | self.restoreDate = None 52 | """ The date when the Medicinal Product is placed on the market by the 53 | Marketing Authorisation Holder (or where applicable, the 54 | manufacturer/distributor) in a country and/or jurisdiction shall be 55 | provided A complete date consisting of day, month and year shall be 56 | specified using the ISO 8601 date format NOTE “Placed on the 57 | market” refers to the release of the Medicinal Product into the 58 | distribution chain. 59 | Type `FHIRDate` (represented as `str` in JSON). """ 60 | 61 | self.status = None 62 | """ This attribute provides information on the status of the marketing 63 | of the medicinal product See ISO/TS 20443 for more information and 64 | examples. 65 | Type `CodeableConcept` (represented as `dict` in JSON). """ 66 | 67 | super(MarketingStatus, self).__init__(jsondict=jsondict, strict=strict, **kwargs) 68 | 69 | def elementProperties(self): 70 | js = super(MarketingStatus, self).elementProperties() 71 | js.extend([ 72 | ("country", "country", codeableconcept.CodeableConcept, False, None, True), 73 | ("dateRange", "dateRange", period.Period, False, None, True), 74 | ("jurisdiction", "jurisdiction", codeableconcept.CodeableConcept, False, None, False), 75 | ("restoreDate", "restoreDate", fhirdate.FHIRDate, False, None, False), 76 | ("status", "status", codeableconcept.CodeableConcept, False, None, True), 77 | ]) 78 | return js 79 | 80 | 81 | import sys 82 | try: 83 | from . import codeableconcept 84 | except ImportError: 85 | codeableconcept = sys.modules[__package__ + '.codeableconcept'] 86 | try: 87 | from . import fhirdate 88 | except ImportError: 89 | fhirdate = sys.modules[__package__ + '.fhirdate'] 90 | try: 91 | from . import period 92 | except ImportError: 93 | period = sys.modules[__package__ + '.period'] -------------------------------------------------------------------------------- /examples/pymodm_autogenerated/tools/fhirloader.py: -------------------------------------------------------------------------------- 1 | # This is part of https://github.com/smart-on-fhir/fhir-parser 2 | # and has been modified for use in fhirbug 3 | 4 | # Copyright 2015 Boston Children's Hospital 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | 18 | import io 19 | import os.path 20 | import logging 21 | 22 | # desired log level 23 | log_level = logging.DEBUG 24 | 25 | # use "logger.logger.log()" 26 | logging.root.setLevel(log_level) 27 | logger = logging.getLogger('fhirparser') 28 | stream = logging.StreamHandler() 29 | stream.setLevel(log_level) 30 | logger.addHandler(stream) 31 | 32 | 33 | class FHIRLoader(object): 34 | """ Class to download the files needed for the generator. 35 | 36 | The `needs` dictionary contains as key the local file needed and how to 37 | get it from the specification URL. 38 | """ 39 | needs = { 40 | 'version.info': 'version.info', 41 | 'profiles-resources.json': 'examples-json.zip', 42 | } 43 | 44 | def __init__(self, settings, cache): 45 | self.settings = settings 46 | self.base_url = settings.specification_url 47 | self.cache = cache 48 | 49 | def load(self, force_download=False, force_cache=False): 50 | """ Makes sure all the files needed have been downloaded. 51 | 52 | :returns: The path to the directory with all our files. 53 | """ 54 | if force_download: assert not force_cache 55 | 56 | if os.path.isdir(self.cache) and force_download: 57 | import shutil 58 | shutil.rmtree(self.cache) 59 | 60 | if not os.path.isdir(self.cache): 61 | os.mkdir(self.cache) 62 | 63 | # check all files and download if missing 64 | uses_cache = False 65 | for local, remote in self.__class__.needs.items(): 66 | path = os.path.join(self.cache, local) 67 | 68 | if not os.path.exists(path): 69 | if force_cache: 70 | raise Exception('Resource missing from cache: {}'.format(local)) 71 | logger.info('Downloading {}'.format(remote)) 72 | filename = self.download(remote) 73 | 74 | # unzip 75 | if '.zip' == filename[-4:]: 76 | logger.info('Extracting {}'.format(filename)) 77 | self.expand(filename) 78 | else: 79 | uses_cache = True 80 | 81 | if uses_cache: 82 | logger.info('Using cached resources, supply "-f" to re-download') 83 | 84 | return self.cache 85 | 86 | def download(self, filename): 87 | """ Download the given file located on the server. 88 | 89 | :returns: The local file name in our cache directory the file was 90 | downloaded to 91 | """ 92 | import requests # import here as we can bypass its use with a manual download 93 | 94 | url = self.base_url+'/'+filename 95 | path = os.path.join(self.cache, filename) 96 | 97 | ret = requests.get(url) 98 | if not ret.ok: 99 | raise Exception("Failed to download {}".format(url)) 100 | with io.open(path, 'wb') as handle: 101 | for chunk in ret.iter_content(): 102 | handle.write(chunk) 103 | 104 | return filename 105 | 106 | def expand(self, local): 107 | """ Expand the ZIP file at the given path to the cache directory. 108 | """ 109 | path = os.path.join(self.cache, local) 110 | assert os.path.exists(path) 111 | import zipfile # import here as we can bypass its use with a manual unzip 112 | 113 | with zipfile.ZipFile(path) as z: 114 | z.extractall(self.cache) 115 | --------------------------------------------------------------------------------