-
Notifications
You must be signed in to change notification settings - Fork 4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for GSF v3.09 #125
Changes from 11 commits
ab57304
293305e
21368c0
7c6cd5c
e83c933
4f387aa
8490512
0e82cd0
6a7017c
c1515bd
e1fd076
72724bc
8e1574a
5b95bc2
3dfeec3
38e96ab
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,11 +5,21 @@ | |
Python wrapper for the C implementation of the Generic Sensor Format library. | ||
|
||
- Free software: MIT license | ||
- __Notes on licensing__: The bundled `libgsf/libgsf03_08.so` is covered by the [LGPL v2.1](https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html) license. A copy of this license is included in the project at `libgsf/libgsf_LICENSE.md`. This does not affect the top-level MIT licensing of the project. However, as required by the libgsf license, the libgsf shared object library used by gsfpy at runtime may be replaced with a different version by setting the `GSFPY_LIBGSF_PATH` environment variable to the absolute file path of the new library. | ||
- __Notes on licensing__: The bundled `gsfpy3_0x/libgsf/libgsf03_0x.so` binaries are covered by the [LGPL v2.1](https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html) license. Copies of this license are included in the project at `gsfpy3_0x/libgsf/libgsf_LICENSE.md`. The top-level MIT licensing of the overall `gsfpy` project is not affected by this. However, as required by the libgsf license, the libgsf shared object libraries used by the `gsfpy3_0x` packages at runtime may be replaced with a different version by setting the `GSFPY3_08_LIBGSF_PATH` and/or `GSFPY3_09_LIBGSF_PATH` environment variables to the absolute file path of the new library. | ||
|
||
## Namespaces and supported GSF versions | ||
The `gsfpy` package provides three namespaces: `gsfpy`, `gsfpy3_08` and `gsfpy3_09`. | ||
|
||
The default version of GSF supported is `3.08`. Top level package functionality for `3.08` can be used either via `import gsfpy` (without setting the `DEFAULT_GSF_VERSION` environment variable - see below) or `import gsfpy3_08`. Note that `import gsfpy` will also work for versions 3.06 and 3.07 of GSF as well (older versions have not been tested). | ||
|
||
If you are using GSF v3.09, there are two options: | ||
* Set the `DEFAULT_GSF_VERSION` environment variable to `"3.09"`, then `import gsfpy` | ||
* Import the 3.09 package directly with `import gsfpy3_09` | ||
|
||
|
||
## Features | ||
|
||
- gsfpy.bindings provides wrappers for all GSFlib functions, including I/O, utility and info functions. | ||
- The `gsfpy(3_0x).bindings` modules provide wrappers for all GSFlib functions, including I/O, utility and info functions. | ||
Minor exceptions are noted in the sections below. | ||
|
||
- For added convenience the gsfpy top level package provides the following higher level abstractions: | ||
|
@@ -29,22 +39,22 @@ pip install gsfpy | |
``` | ||
#### From GitHub (SSH) | ||
```shell script | ||
pip install git+ssh://[email protected]/UKHO/gsfpy.git@master | ||
pip install git+ssh://[email protected]/UKHO/gsfpy3_08.git@master | ||
``` | ||
#### From GitHub (HTTPS) | ||
```shell script | ||
pip install git+https://github.com/UKHO/gsfpy.git@master | ||
pip install git+https://github.com/UKHO/gsfpy3_08.git@master | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are these path's correct? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed |
||
``` | ||
|
||
## Examples of usage | ||
|
||
### Open/close/read from a GSF file | ||
### Open/close/read from a GSF file (GSF v3.08) | ||
|
||
```python | ||
from ctypes import string_at | ||
|
||
from gsfpy import open_gsf | ||
from gsfpy.enums import RecordType | ||
from gsfpy3_08 import open_gsf | ||
from gsfpy3_08.enums import RecordType | ||
|
||
with open_gsf("path/to/file.gsf") as gsf_file: | ||
# Note - file is closed automatically upon exiting 'with' block | ||
|
@@ -55,16 +65,16 @@ with open_gsf("path/to/file.gsf") as gsf_file: | |
print(string_at(record.comment.comment)) | ||
``` | ||
|
||
### Write to a GSF file | ||
### Write to a GSF file (GSF v3.09) | ||
|
||
```python | ||
from ctypes import c_int, create_string_buffer | ||
|
||
from gsfpy import open_gsf | ||
from gsfpy.enums import FileMode, RecordType | ||
from gsfpy.gsfRecords import c_gsfRecords | ||
from gsfpy3_09 import open_gsf | ||
from gsfpy3_09.enums import FileMode, RecordType | ||
from gsfpy3_09.gsfRecords import c_gsfRecords | ||
|
||
comment = "My comment" | ||
comment = b"My comment" | ||
|
||
# Initialize the contents of the record that will be written. | ||
# Note use of ctypes.create_string_buffer() to set POINTER(c_char) contents. | ||
|
@@ -77,32 +87,29 @@ with open_gsf("path/to/file.gsf", mode=FileMode.GSF_CREATE) as gsf_file: | |
gsf_file.write(record, RecordType.GSF_RECORD_COMMENT) | ||
``` | ||
|
||
### Copy GSF records | ||
### Copy GSF records (GSF v3.08 as default) | ||
|
||
```python | ||
from ctypes import byref, c_int, pointer | ||
|
||
import gsfpy | ||
from gsfpy.enums import FileMode, RecordType | ||
from gsfpy.gsfDataID import c_gsfDataID | ||
from gsfpy.gsfRecords import c_gsfRecords | ||
from gsfpy import * | ||
|
||
|
||
# This example uses gsfpy.bindings to illustrate use of the lower level functions | ||
# This example uses the bindings module to illustrate use of the lower level functions | ||
file_handle = c_int(0) | ||
data_id = c_gsfDataID() | ||
source_records = c_gsfRecords() | ||
target_records = c_gsfRecords() | ||
data_id = gsfDataID.c_gsfDataID() | ||
source_records = gsfRecords.c_gsfRecords() | ||
target_records = gsfRecords.c_gsfRecords() | ||
|
||
ret_val_open = gsfpy.bindings.gsfOpen( | ||
"path/to/file.gsf", FileMode.GSF_READONLY, byref(file_handle) | ||
ret_val_open = bindings.gsfOpen( | ||
b"path/to/file.gsf", enums.FileMode.GSF_READONLY, byref(file_handle) | ||
) | ||
|
||
# Note use of ctypes.byref() as a shorthand way of passing POINTER parameters to | ||
# the underlying foreign function call. ctypes.pointer() may also be used. | ||
bytes_read = gsfpy.bindings.gsfRead( | ||
file_handle, | ||
RecordType.GSF_RECORD_COMMENT, | ||
enums.RecordType.GSF_RECORD_COMMENT, | ||
byref(data_id), | ||
byref(source_records), | ||
) | ||
|
@@ -112,23 +119,23 @@ bytes_read = gsfpy.bindings.gsfRead( | |
# the native underlying function causes memory ownership clashes. byref() | ||
# is only suitable for passing parameters to foreign function calls (see | ||
# ctypes docs). | ||
ret_val_cpy = gsfpy.bindings.gsfCopyRecords( | ||
ret_val_cpy = bindings.gsfCopyRecords( | ||
pointer(target_records), pointer(source_records) | ||
) | ||
ret_val_close = gsfpy.bindings.gsfClose(file_handle) | ||
ret_val_close = bindings.gsfClose(file_handle) | ||
``` | ||
|
||
### Troubleshoot | ||
|
||
```python | ||
import gsfpy | ||
from gsfpy3_09.bindings import gsfIntError, gsfStringError | ||
|
||
# The gsfIntError() and gsfStringError() functions are useful for | ||
# diagnostics. They return an error code and corresponding error | ||
# message, respectively. | ||
retValIntError = gsfpy.bindings.gsfIntError() | ||
retValStringError = gsfpy.bindings.gsfStringError() | ||
print(retValStringError) | ||
retValIntError = gsfIntError() | ||
retValStringError = gsfStringError() | ||
print(retValIntError, retValStringError) | ||
``` | ||
|
||
## Notes on implementation | ||
|
@@ -174,7 +181,7 @@ More recent versions of these documents can be downloaded from the | |
By default Poetry will create it's own virtual environment using your system's Python. [This feature can be disabled.](https://python-poetry.org/docs/faq/#i-dont-want-poetry-to-manage-my-virtual-environments-can-i-disable-it) | ||
|
||
```shell script | ||
git clone [email protected]:UKHO/gsfpy.git | ||
git clone [email protected]:UKHO/gsfpy3_08.git | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As above There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed |
||
cd gsfpy | ||
poetry install | ||
``` | ||
|
@@ -184,7 +191,7 @@ poetry install | |
A good choice if you want to run a version of Python different than available through your system's package manager | ||
|
||
```shell script | ||
git clone [email protected]:UKHO/gsfpy.git | ||
git clone [email protected]:UKHO/gsfpy3_08.git | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As above There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed |
||
cd gsfpy | ||
pyenv install 3.8.3 | ||
pyenv virtualenv 3.8.3 gsfpy | ||
|
@@ -216,7 +223,7 @@ calling gsfpy to assess these risks and mitigate where deemed necessary. | |
GSF data processed using gsfpy should be sourced from reliable providers | ||
and checked for integrity where possible. | ||
|
||
Please also refer to the LICENSE file for the terms of use of gsfpy. | ||
Please also refer to the LICENSE file for the terms of use of gsfpy3_08. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As above There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed |
||
|
||
## Credits | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,3 @@ | ||
from ctypes import Structure, c_double | ||
from gsfpy import mirror_default_gsf_version_submodule | ||
|
||
|
||
class c_GSF_POSITION(Structure): | ||
_fields_ = [ | ||
("lon", c_double), | ||
("lat", c_double), | ||
("z", c_double), | ||
] | ||
mirror_default_gsf_version_submodule(globals(), "GSF_POSITION") |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,3 @@ | ||
from ctypes import Structure, c_double | ||
from gsfpy import mirror_default_gsf_version_submodule | ||
|
||
|
||
# Note: the coordinate system is: | ||
# +x forward, +y starboard, + z down, +hdg cw from north | ||
class c_GSF_POSITION_OFFSETS(Structure): | ||
_fields_ = [ | ||
("x", c_double), | ||
("y", c_double), | ||
("z", c_double), | ||
] | ||
mirror_default_gsf_version_submodule(globals(), "GSF_POSITION_OFFSETS") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a reason these are run individually rather than just pointing pytest at the tests folder?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is a reason! Once a module is loaded in python it is almost impossible to unload it. Therefore for tests which are checking the gsfpy behaviour of loading the correct version-specific namespace based on the DEFAULT_GSF_VERSION env variable, or loading custom versions of the libgsf shared object libraries, it is necessary to execute these in their own dedicated pytest runs.