diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml new file mode 100644 index 00000000..5d0ae1ba --- /dev/null +++ b/.github/workflows/ci.yaml @@ -0,0 +1,38 @@ +name: CI +on: + pull_request: + push: + branches: + - main + +# The goal here is to cancel older workflows when a PR is updated (because it's pointless work) +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.ref_name }} + cancel-in-progress: true + +jobs: + generate: + name: generate + runs-on: ubuntu-latest + strategy: + matrix: + python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"] + + steps: + - uses: actions/checkout@v4 + + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} + cache: pip + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install -r requirements.txt + + - name: Test generation + run: | + echo "from Default.settings import *" > settings.py + ./generate.py diff --git a/.gitignore b/.gitignore index 79461249..be4c3fa3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ *.pyc __pycache__ env +/.idea/ # ignore mappings and settings files /mappings.py diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 53ce36e3..00000000 --- a/.travis.yml +++ /dev/null @@ -1,4 +0,0 @@ -language: python -script: - - echo "from Default.settings import *" > settings.py - - ./generate.py \ No newline at end of file diff --git a/Default/mappings.py b/Default/mappings.py index 973d96fe..dcbac0ae 100644 --- a/Default/mappings.py +++ b/Default/mappings.py @@ -5,7 +5,7 @@ # Which class names to map to resources and elements classmap = { 'Any': 'Resource', - 'Practitioner.role': 'PractRole', # to avoid Practinioner.role and PractitionerRole generating the same class + 'Practitioner.role': 'PractRole', # to avoid Practitioner.role and PractitionerRole generating the same class 'boolean': 'bool', 'integer': 'int', diff --git a/README.md b/README.md index ba7dcdc5..8f6615a9 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,12 @@ Python FHIR Parser ================== -[![Build Status](https://travis-ci.org/palfrey/fhir-parser.svg?branch=master)](https://travis-ci.org/palfrey/fhir-parser) - A Python FHIR specification parser for model class generation. If you've come here because you want _Swift_ or _Python_ classes for FHIR data models, look at our client libraries instead: - [Swift-FHIR][] and [Swift-SMART][] - Python [client-py][] -The `master` branch is currently capable of parsing _STU 3, v3.0.0_. -The `develop` branch should be capable of parsing the continuous integration build and will be merged into master on new major FHIR releases. -There may be tags for specific freezes, see [releases](https://github.com/smart-on-fhir/fhir-parser/releases). +The `main` branch is currently capable of parsing _R5_. This work is licensed under the [APACHE license][license]. FHIR® is the registered trademark of [HL7][] and is used with the permission of HL7. @@ -26,7 +22,7 @@ These representations are then used by [Jinja][] templates to create classes in This script does its job for the most part, but it doesn't yet handle all FHIR peculiarities and there's no guarantee the output is correct or complete. This repository **does not include the templates and base classes** needed for class generation, you must do this yourself in your project. You will typically add this repo as a submodule to your framework project, create a directory that contains the necessary base classes and templates, create _settings_ and _mappings_ files and run the script. -Examples on what you would need to do for Python classes can be found in _Sample/settings.py_, _Sample/mappings.py_ and _Sample/templates*_. +Examples on what you would need to do for Python classes can be found in _Default/settings.py_, _Default/mappings.py_ and _Sample/templates*_. Use diff --git a/fhirrenderer.py b/fhirrenderer.py index 5c735734..77e66c6b 100644 --- a/fhirrenderer.py +++ b/fhirrenderer.py @@ -8,7 +8,7 @@ import textwrap from jinja2 import Environment, PackageLoader, TemplateNotFound -from jinja2.filters import environmentfilter +from jinja2.filters import pass_environment from logger import logger @@ -202,7 +202,7 @@ def render(self): # ignores existing linebreaks when applying the wrap: # https://github.com/mitsuhiko/jinja2/issues/175 # Here's the workaround: -@environmentfilter +@pass_environment def do_wordwrap(environment, s, width=79, break_long_words=True, wrapstring=None): """ Return a copy of the string passed to the filter wrapped after @@ -211,7 +211,7 @@ def do_wordwrap(environment, s, width=79, break_long_words=True, wrapstring=None split words apart if they are longer than `width`. """ if not s: - return s + return s if not wrapstring: wrapstring = environment.newline_sequence @@ -220,7 +220,7 @@ def do_wordwrap(environment, s, width=79, break_long_words=True, wrapstring=None # Workaround: pre-split the string on \r, \r\n and \n for component in re.split(r"\r\n|\n|\r", s): # textwrap will eat empty strings for breakfirst. Therefore we route them around it. - if len(component) is 0: + if len(component) == 0: accumulator.append(component) continue accumulator.extend( diff --git a/fhirspec.py b/fhirspec.py index 3a9fa692..a7ec0d66 100644 --- a/fhirspec.py +++ b/fhirspec.py @@ -623,7 +623,7 @@ def needed_external_classes(self): raise Exception('There is no class "{}" for property "{}" on "{}" in {}'.format(prop_cls_name, prop.name, klass.name, self.name)) else: prop.module_name = prop_cls.module - if not prop_cls_name in needed: + if prop_cls_name not in needed: needed.add(prop_cls_name) needs.append(prop_cls) diff --git a/requirements.txt b/requirements.txt index eb82609a..6e0bcb5f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,3 @@ -Jinja2>=2.9.5 -MarkupSafe==0.23 +colorlog>=2.10.0 +jinja2>=3.0 requests>=2.13.0 -colorlog==2.10.0