# xerparser
Read the contents of a P6 .xer file and convert it into a Python object.
*Disclaimers:
It's helpfull if you are already familiar with the mapping and schemas used by P6 during the export process.
Refer to the [Oracle Documentation]( https://docs.oracle.com/cd/F25600_01/English/Mapping_and_Schema/xer_import_export_data_map_project/index.htm) for more information regarding how data is mapped to the XER format.
Tested on .xer files exported as versions 15.2 through 19.12.*
<br/>
## Install
**Windows**:
```bash
pip install xerparser
```
**Linux/Mac**:
```bash
pip3 install xerparser
```
<br/>
## Usage
Import the `Xer` class from `xerparser` and pass the contents of a .xer file as an argument. Use the `Xer` class variable `CODEC` to set the proper encoding to decode the file.
```python
from xerparser import Xer
file = r"/path/to/file.xer"
with open(file, encoding=Xer.CODEC, errors="ignore") as f:
file_contents = f.read()
xer = Xer(file_contents)
```
Do not pass the the .xer file directly as an argument to the `Xer` class. The file must be decoded and read into a string, which can then be passed as an argument. Or, pass the .xer file into the `Xer.reader` classmethod, which accepts:
* str or pathlib.Path objects for files stored locally or on a server.
* Binary files from requests, Flask, FastAPI, etc...
```python
from xerparser import Xer
file = r"/path/to/file.xer"
xer = Xer.reader(file)
```
<br/>
## Attributes
The tables stored in the .xer file are accessable as either Global, Project specific, Task specific, or Resource specific:
### Global
```python
xer.export_info # export data
xer.activity_code_types # dict of ACTVTYPE objects
xer.activity_code_values # dict of ACTVCODE objects
xer.calendars # dict of all CALENDAR objects
xer.financial_periods # dict of FINDATES objects
xer.notebook_topics # dict of MEMOTYPE objects
xer.projects # dict of PROJECT objects
xer.project_code_types # dict of PCATTYPE objects
xer.project_code_values # dict of PCATVAL objects
xer.tasks # dict of all TASK objects
xer.relationships # dict of all TASKPRED objects
xer.resources # dict of RSRC objects
xer.resource_rates # dict of RSRCRATE objects
xer.udf_types # dict of UDFTYPE objects
xer.wbs_nodes # dict of all PROJWBS objects
```
### Project Specific
```python
# Get first project
project = list(xer.projects.values())[0]
project.activity_codes # list of project specific ACTVTYPE objects
project.calendars # list of project specific CALENDAR objects
project.project_codes # dict of PCATTYPE: PCATVAL objects
project.tasks # list of project specific TASK objects
project.relationships # list of project specific TASKPRED objects
project.resources # lest of project specific TASKRSRC objects
project.user_defined_fields # dict of `UDFTYPE`: `UDF Value` pairs
project.wbs_nodes # list of project specific PROJWBS objects
```
### WBS Specific
```python
# Get projects root wbs node
wbs_node = project.wbs_root
wbs_node.children # list of child PROJWBS objects
wbs_node.project # PROJECT the WBS node belongs to
wbs_node.tasks # list of TASK objects assigned directly to WBS node
wbs_node.all_tasks # list of TASK objects under the WBS node
wbs_node.user_defined_fields # dict of `UDFTYPE`: `UDF Value` pairs
```
### Task Specific
```python
# Get first task
task = project.tasks[0]
task.activity_codes # dict of ACTVTYPE: ACTVCODE objects
task.memos # list of TASKMEMO objects
task.periods # list of TASKFIN objects
task.resources # dict of TASKRSRC objects
task.user_defined_fields # dict of `UDFTYPE`: `UDF Value` pairs
```
### Resource Specific
```python
# Get first task resource
resource = list(task.resources.values())[0]
resource.periods # list of TRSRCFIN objects
resource.user_defined_fields # dict of `UDFTYPE`: `UDF Value` pairs
```
<br/>
## Error Checking
Sometimes the xer file is corrupted during the export process. If this is the case, a `CorruptXerFile` Exception will be raised during initialization. A list of the errors can be accessed from the `CorruptXerFile` Exception, or by using the `find_xer_errors` function.
### Option 1 - `errors` attribute of `CorruptXerFile` exception (preferred)
```python
from xerparser import Xer, CorruptXerFile
file = r"/path/to/file.xer"
try:
xer = Xer.reader(file)
except CorruptXerFile as e:
for error in e.errors:
print(error)
```
### Option 2 - `find_xer_errors` function
```python
from xerparser import parser, file_reader, find_xer_errors
file = r"/path/to/file.xer"
xer_data = parser(file_reader(file))
file_errors = find_xer_errors(xer_data)
for error in file_errors:
print(error)
```
### Errors
- Minimum required tables - an error is recorded if one of the following tables is missing:
- CALENDAR
- PROJECT
- PROJWBS
- TASK
- TASKPRED
- Required table pairs - an error is recorded if Table 1 is included but not Table 2:
| Table 1 | Table 2 | Notes |
| :----------- |:-------------|----------|
| TASKFIN | FINDATES | *Financial Period Data for Task* |
| TRSRCFIN | FINDATES | *Financial Period Data for Task Resource* |
| TASKRSRC | RSRC | *Resource Data* |
| TASKMEMO | MEMOTYPE | *Notebook Data* |
| ACTVCODE | ACTVTYPE | *Activity Code Data* |
| TASKACTV | ACTVCODE | *Activity Code Data* |
| PCATVAL | PCATTYPE | *Project Code Data* |
| PROJPCAT | PCATVAL | *Project Code Data* |
| UDFVALUE | UDFTYPE | *User Defined Field Data* |
- Non-existent calendars assigned to tasks.
- Non-existent resources assigned to task resources.
Raw data
{
"_id": null,
"home_page": "https://github.com/jjCode01/xerparser",
"name": "xerparser",
"maintainer": null,
"docs_url": null,
"requires_python": "<4.0,>=3.11",
"maintainer_email": null,
"keywords": "primavera, p6, xer, schedule, scheduling, planning, project management, project controls",
"author": "Jesse",
"author_email": "code@seqmanagement.com",
"download_url": "https://files.pythonhosted.org/packages/ff/85/7a8158449c2d994e87a46b9fd719f7de3d8bc3f5eb7daeab42a14ea10c68/xerparser-0.13.4.tar.gz",
"platform": null,
"description": "# xerparser\n\nRead the contents of a P6 .xer file and convert it into a Python object. \n\n*Disclaimers: \nIt's helpfull if you are already familiar with the mapping and schemas used by P6 during the export process.\nRefer to the [Oracle Documentation]( https://docs.oracle.com/cd/F25600_01/English/Mapping_and_Schema/xer_import_export_data_map_project/index.htm) for more information regarding how data is mapped to the XER format. \nTested on .xer files exported as versions 15.2 through 19.12.* \n\n<br/>\n\n## Install\n\n**Windows**:\n\n```bash\npip install xerparser\n```\n\n**Linux/Mac**:\n\n```bash\npip3 install xerparser\n```\n\n<br/> \n\n## Usage \n\nImport the `Xer` class from `xerparser` and pass the contents of a .xer file as an argument. Use the `Xer` class variable `CODEC` to set the proper encoding to decode the file.\n\n```python\nfrom xerparser import Xer\n\nfile = r\"/path/to/file.xer\"\nwith open(file, encoding=Xer.CODEC, errors=\"ignore\") as f:\n file_contents = f.read()\nxer = Xer(file_contents)\n```\n\nDo not pass the the .xer file directly as an argument to the `Xer` class. The file must be decoded and read into a string, which can then be passed as an argument. Or, pass the .xer file into the `Xer.reader` classmethod, which accepts:\n\n* str or pathlib.Path objects for files stored locally or on a server.\n* Binary files from requests, Flask, FastAPI, etc...\n\n```python\nfrom xerparser import Xer\n\nfile = r\"/path/to/file.xer\"\nxer = Xer.reader(file)\n```\n\n<br/>\n\n## Attributes\n\nThe tables stored in the .xer file are accessable as either Global, Project specific, Task specific, or Resource specific:\n\n### Global\n\n ```python\n xer.export_info # export data\n xer.activity_code_types # dict of ACTVTYPE objects\n xer.activity_code_values # dict of ACTVCODE objects\n xer.calendars # dict of all CALENDAR objects\n xer.financial_periods # dict of FINDATES objects\n xer.notebook_topics # dict of MEMOTYPE objects\n xer.projects # dict of PROJECT objects\n xer.project_code_types # dict of PCATTYPE objects\n xer.project_code_values # dict of PCATVAL objects\n xer.tasks # dict of all TASK objects\n xer.relationships # dict of all TASKPRED objects\n xer.resources # dict of RSRC objects\n xer.resource_rates # dict of RSRCRATE objects\n xer.udf_types # dict of UDFTYPE objects\n xer.wbs_nodes # dict of all PROJWBS objects\n ``` \n\n### Project Specific\n\n```python\n# Get first project\nproject = list(xer.projects.values())[0]\n\nproject.activity_codes # list of project specific ACTVTYPE objects\nproject.calendars # list of project specific CALENDAR objects\nproject.project_codes # dict of PCATTYPE: PCATVAL objects\nproject.tasks # list of project specific TASK objects\nproject.relationships # list of project specific TASKPRED objects\nproject.resources # lest of project specific TASKRSRC objects\nproject.user_defined_fields # dict of `UDFTYPE`: `UDF Value` pairs \nproject.wbs_nodes # list of project specific PROJWBS objects\n```\n\n### WBS Specific\n```python\n# Get projects root wbs node\nwbs_node = project.wbs_root\n\nwbs_node.children # list of child PROJWBS objects\nwbs_node.project # PROJECT the WBS node belongs to\nwbs_node.tasks # list of TASK objects assigned directly to WBS node\nwbs_node.all_tasks # list of TASK objects under the WBS node\nwbs_node.user_defined_fields # dict of `UDFTYPE`: `UDF Value` pairs \n```\n\n### Task Specific\n\n```python\n# Get first task\ntask = project.tasks[0]\n\ntask.activity_codes # dict of ACTVTYPE: ACTVCODE objects\ntask.memos # list of TASKMEMO objects\ntask.periods # list of TASKFIN objects\ntask.resources # dict of TASKRSRC objects\ntask.user_defined_fields # dict of `UDFTYPE`: `UDF Value` pairs \n```\n\n### Resource Specific\n\n```python\n# Get first task resource\nresource = list(task.resources.values())[0]\n\nresource.periods # list of TRSRCFIN objects\nresource.user_defined_fields # dict of `UDFTYPE`: `UDF Value` pairs \n```\n\n<br/>\n\n## Error Checking\n\nSometimes the xer file is corrupted during the export process. If this is the case, a `CorruptXerFile` Exception will be raised during initialization. A list of the errors can be accessed from the `CorruptXerFile` Exception, or by using the `find_xer_errors` function.\n\n### Option 1 - `errors` attribute of `CorruptXerFile` exception (preferred)\n```python\nfrom xerparser import Xer, CorruptXerFile\n\nfile = r\"/path/to/file.xer\"\ntry:\n xer = Xer.reader(file)\nexcept CorruptXerFile as e:\n for error in e.errors:\n print(error)\n``` \n\n### Option 2 - `find_xer_errors` function\n```python\nfrom xerparser import parser, file_reader, find_xer_errors\n\nfile = r\"/path/to/file.xer\"\nxer_data = parser(file_reader(file))\nfile_errors = find_xer_errors(xer_data)\nfor error in file_errors:\n print(error)\n```\n\n### Errors\n\n- Minimum required tables - an error is recorded if one of the following tables is missing:\n - CALENDAR\n - PROJECT\n - PROJWBS\n - TASK\n - TASKPRED \n- Required table pairs - an error is recorded if Table 1 is included but not Table 2: \n \n | Table 1 | Table 2 | Notes |\n | :----------- |:-------------|----------|\n | TASKFIN | FINDATES | *Financial Period Data for Task* |\n | TRSRCFIN | FINDATES | *Financial Period Data for Task Resource* |\n | TASKRSRC | RSRC | *Resource Data* |\n | TASKMEMO | MEMOTYPE | *Notebook Data* |\n | ACTVCODE | ACTVTYPE | *Activity Code Data* |\n | TASKACTV | ACTVCODE | *Activity Code Data* |\n | PCATVAL | PCATTYPE | *Project Code Data* |\n | PROJPCAT | PCATVAL | *Project Code Data* |\n | UDFVALUE | UDFTYPE | *User Defined Field Data* |\n\n- Non-existent calendars assigned to tasks.\n- Non-existent resources assigned to task resources.\n",
"bugtrack_url": null,
"license": "GPL-3.0-only",
"summary": "Parse a P6 .xer file to a Python object.",
"version": "0.13.4",
"project_urls": {
"Homepage": "https://github.com/jjCode01/xerparser",
"Repository": "https://github.com/jjCode01/xerparser"
},
"split_keywords": [
"primavera",
" p6",
" xer",
" schedule",
" scheduling",
" planning",
" project management",
" project controls"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "34bb135947e0d6d65defe55f6599b7625f2c86ce9b3518ffecd8271b77f64694",
"md5": "6658148f052b78c6bbd8269ec4db4d35",
"sha256": "8e45919fc98b24752a2ebbc0184ba4c11d0024674b8bf45c717e0ac6b73186f9"
},
"downloads": -1,
"filename": "xerparser-0.13.4-py3-none-any.whl",
"has_sig": false,
"md5_digest": "6658148f052b78c6bbd8269ec4db4d35",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": "<4.0,>=3.11",
"size": 49074,
"upload_time": "2024-12-19T03:24:43",
"upload_time_iso_8601": "2024-12-19T03:24:43.039572Z",
"url": "https://files.pythonhosted.org/packages/34/bb/135947e0d6d65defe55f6599b7625f2c86ce9b3518ffecd8271b77f64694/xerparser-0.13.4-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "ff857a8158449c2d994e87a46b9fd719f7de3d8bc3f5eb7daeab42a14ea10c68",
"md5": "20e101012b272f36e30e893767bd8d8a",
"sha256": "2609eb2d69967e786764b12c90351f9f47582157a8f0bbdcc519f76d51ec9378"
},
"downloads": -1,
"filename": "xerparser-0.13.4.tar.gz",
"has_sig": false,
"md5_digest": "20e101012b272f36e30e893767bd8d8a",
"packagetype": "sdist",
"python_version": "source",
"requires_python": "<4.0,>=3.11",
"size": 38385,
"upload_time": "2024-12-19T03:24:45",
"upload_time_iso_8601": "2024-12-19T03:24:45.675590Z",
"url": "https://files.pythonhosted.org/packages/ff/85/7a8158449c2d994e87a46b9fd719f7de3d8bc3f5eb7daeab42a14ea10c68/xerparser-0.13.4.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-12-19 03:24:45",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "jjCode01",
"github_project": "xerparser",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"lcname": "xerparser"
}