pyGNparser 0.0.5
Python client for GNparser
License: MIT
Keywords: biodiversity, scientific names, parser, nomenclature, taxonomy, API, web-services, species, natural history, taxonomists, biologists, Global Names

# pyGNparser

![https://img.shields.io/pypi/v/pygnparser.svg](https://pypi.python.org/pypi/pygnparser) ![https://github.com/gnames/pygnparser/workflows/Python/badge.svg](https://github.com/gnames/pygnparser/actions?query=workflow%3APython)

This is a Python wrapper on the [GNparser](https://parser.globalnames.org/) API. Code follow the spirit/approach of the [pygbif](https://github.com/gbif/pygbif/graphs/contributors) package, and indeed much of the wrapping utility is copied 1:1 from that repo, thanks [@sckott](https://github.com/sckott) and other [contributors](https://github.com/gbif/pygbif/graphs/contributors).

## Installation

Add this line to your application's requirements.txt:

```python
pygnparser
```

And then execute:

    $ pip install -r requirements.txt

Or install it yourself as:

    $ pip install pygnparser

## Usage


Import the library:
```
from pygnparser import gnparser
```

If you have a local installation of gnparser, set the GNPARSER_BASE_URL to the host and port that the service is running on, for example if running locally on port 8787:

```python
GNPARSER_BASE_URL = "http://localhost:8787/"
```

Without the GNPARSER_BASE_URL environment variable set, the wrapper will default to using the remote API which will perform slower: https://parser.globalnames.org/


---
### Parse a scientific name
Parse a scientific name:
```python
>>> result = gnparser('Ursus arctos Linnaeus, 1758') #  => Dictionary
```

Check if parsed:
```python
>>> result.parsed() #  => Boolean
True
```

Get [parsed quality](https://github.com/gnames/gnparser#figuring-out-if-names-are-well-formed):
```python
>>> result.quality() #  => Integer
1
```

Get the genus name:
```python
>>> result.genus() #  => String
'Ursus'
```

Get the species name:
```python
>>> result.species() #  => String
'arctos'
```

Get the year:
```python
>>> result.year() #  => String
'1758'
```

Get the authorship:
```python
>>> result.authorship() #  => String
'(Linnaeus, 1758)'
```

Get the scientific name without the Latin gender stem:
```python
>>> result.canonical_stemmed() #  => String
'Ursus arct'
```

Get the parsed name components for a hybrid formula:
```python
>>> result = gnparser('Isoetes lacustris × stricta Gay') #  => Dictionary
>>> result.is_hybrid() #  => Boolean
True
>>> result.hybrid() #  => String
'HYBRID_FORMULA'
>>> result.normalized() #  => String
'Isoetes lacustris × Isoetes stricta Gay'
>>> result.hybrid_formula_ranks() #  => Array
['species', 'species']
>>> res.hybrid_formula_genera() #  => Array
['Isoetes', 'Isoetes']
>>> res.hybrid_formula_species() #  => Array
['lacustris', 'stricta']
>>> res.hybrid_formula_authorship() #  => Array
['', 'Gay']
```

Parse a scientific name under a specified nomenclatural code:
```python
>>> result = gnparser('Malus domestica \'Fuji\'', code='cultivar')
>>> result.is_cultivar() #  => Boolean
True
>>> result.genus() #  => String
'Malus'
>>> result.species() #  => String
'domestica'
>>> result.cultivar() #  => String
'‘Fuji’'
>>> result.nomenclatural_code() #  => String
'ICNCP'
```

---
### Parse multiple scientific names
Parse multiple scientific names by separating them with `\r\n`:
```python
results = gnparser('Ursus arctos Linnaeus, 1758\r\nAlces alces (Linnaeus, 1758)\r\nRangifer tarandus (Linnaeus, 1758)\r\nUrsus maritimus (Phipps, 1774') #  => Array
```

Get the genus of the 1st parsed name in the list:
```python
results[0].genus() #  => String
'Ursus'
```

---
## Deviations

Some extra helpers are included that extend the functionality of GNparser.

1) The page() method gets the page number out of the unparsed tail:
```python
>>> result = gnparser('Ursus arctos Linnaeus, 1758: 81')
result.page()  # => String
'81'
```

2) The authorship() method returns a formatted authorship string depending on the number of authors. If it is one author with a year, it will return as Smith, 1970. For two authors and a year it will return as Smith & Johnson, 1970. For three authors it will return as Smith, Johnson & Jones, 1970. Any additional authors beyond 3 will be comma separated with the last author included with an ampersand.
```python
>>> result = gnparser('Aus bus cus Smith, Johnson, & Jones, 1970')
result.authorship()  # => String
'Smith, Johnson & Jones, 1970'
```

3) The infraspecies() method will return the infraspecies name. Currently there is no special methods for ranks lower than trinomials but you can access them with the infraspecies_details() method. Please [open an issue](https://github.com/gnames/pygnparser/issues/new) if you need it added.
```python
>>> result = gnparser('Aus bus cus')
result.infraspecies()  # => String
'cus'
```

4) At present, GNParser normalizes authorships like `Smith in Jones, 1999` to `Smith ex Jones 1999`. In the Python wrapper, it is possible to override that behavior by setting the `preserve_in_authorship` parameter to `True` when calling the `authorship()`, `authorship_normalized()`, `combination_authorship()`, `original_authorship()`, or `normalized()` functions.
```python
>>> result = gnparser('Aus bus Smith in Jones, 1999')
result.normalized()  # => String
'Aus bus Smith ex Jones 1999'
result.normalized(preserve_in_authorship=True)  # => String
'Aus bus Smith in Jones 1999'
```
* If the verbatim authorship contains `ex`, setting preserve_in_authorship to `True` will not change `ex` to `in`:
```python
>>> result = gnparser('Aus bus Smith ex Jones, 1999')
result.normalized(preserve_in_authorship=True)  # => String
'Aus bus Smith ex Jones 1999'
```

---
## Other GNparser Libraries

* Node.js: [node-gnparser](https://github.com/amazingplants/node-gnparser)
* R: [rgnparser](https://github.com/ropensci/rgnparser)
* Ruby Gem: [biodiversity](https://github.com/GlobalNamesArchitecture/biodiversity)

---
## Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/gnames/pygnparser. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/gnames/pygnparser/blob/main/CODE_OF_CONDUCT.md).

---
## Development

After checking out the repo, change into the package directory `cd pygnparser`, run `pip install .` to install the package, and `pip install -r requirements.txt` to install the dependencies. Then, run `pytest` to run the tests. You can also run `bin/console` for an interactive Python prompt that will allow you to experiment with the above example commands.

---
## License

The package is available as open source under the terms of the [MIT](https://github.com/gnames/pygnparser/blob/main/LICENSE.txt) license. You can learn more about the MIT license on [Wikipedia](https://en.wikipedia.org/wiki/MIT_License) and compare it with other open source licenses at the [Open Source Initiative](https://opensource.org/license/mit/).

---
## Code of Conduct

Everyone interacting in the pyGNparser project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/gnames/pygnparser/blob/main/CODE_OF_CONDUCT.md).


## [Unreleased]

## [0.0.5] - 2024-11-11
- Added nomenclatural code parameter
- Added result methods for cultivars
- Disabled et_al_cutoff formatting by default
- Removed preserve_in_authorship parameter from authorship() because GNparser no longer normalizes `in` to `ex`

## [0.0.4] - 2024-10-15

- Added preserve_in_authorship parameter to authorship() to optionally override normalization of `in` to `ex`

## [0.0.3] - 2024-10-14

- Added uninomial method

## [0.0.2] - 2024-10-10

- Added named hybrid and hybrid formula handling
- Added original authorship and combination authorship handling
- Added et_al_cutoff parameter to authorship formatting

## [0.0.1] - 2024-03-27

- Initial release