{"id":19974264,"url":"https://github.com/gbroques/fcxref","last_synced_at":"2025-10-12T01:07:53.184Z","repository":{"id":57428905,"uuid":"389488114","full_name":"gbroques/fcxref","owner":"gbroques","description":"Manages FreeCAD external references.","archived":false,"fork":false,"pushed_at":"2025-01-03T01:59:06.000Z","size":166,"stargazers_count":9,"open_issues_count":3,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-09-25T04:21:00.604Z","etag":null,"topics":["cross-document","external-link","external-links","find-links","find-references","freecad","freecad-addons","freecad-document","freecad-macro"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"lgpl-2.1","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/gbroques.png","metadata":{"files":{"readme":"README.rst","changelog":"CHANGELOG.rst","contributing":"CONTRIBUTING.rst","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2021-07-26T02:37:33.000Z","updated_at":"2025-09-13T01:02:12.000Z","dependencies_parsed_at":"2025-01-02T04:23:35.754Z","dependency_job_id":"a09acd74-17a6-4dce-87e0-9154ba6a395e","html_url":"https://github.com/gbroques/fcxref","commit_stats":{"total_commits":57,"total_committers":1,"mean_commits":57.0,"dds":0.0,"last_synced_commit":"394eda9cf8ac1f9dd9447b49ca9b3a396f44f866"},"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/gbroques/fcxref","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gbroques%2Ffcxref","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gbroques%2Ffcxref/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gbroques%2Ffcxref/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gbroques%2Ffcxref/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gbroques","download_url":"https://codeload.github.com/gbroques/fcxref/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gbroques%2Ffcxref/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279009668,"owners_count":26084645,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-11T02:00:06.511Z","response_time":55,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cross-document","external-link","external-links","find-links","find-references","freecad","freecad-addons","freecad-document","freecad-macro"],"created_at":"2024-11-13T03:14:28.867Z","updated_at":"2025-10-12T01:07:53.161Z","avatar_url":"https://github.com/gbroques.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"fcxref\n======\n\n|version badge| |downloads badge|\n\n.. |version badge| image:: https://badge.fury.io/py/fcxref.svg\n   :alt: PyPI version\n   :target: https://badge.fury.io/py/fcxref\n\n.. |downloads badge| image:: https://img.shields.io/pypi/dm/fcxref\n   :alt: PyPI - Downloads\n\n----\n\n* `Introduction`_\n* `Motivation`_\n* `Approach`_\n* `Installation`_\n* `Usage`_\n* `Python API`_\n* `Command Line`_\n* `Supported FreeCAD Versions`_\n* `Changelog`_\n* `Contributing`_\n\nIntroduction\n------------\n\nManages **F**\\ ree\\ **C**\\ AD e\\ **x**\\ ternal **ref**\\ erences.\n\n\"External references\" are also known as external links or cross-document references.\n\nThe following operations are supported:\n\n1. *Finding* external references\n2. *Renaming* external references\n3. and *Removing* external references (i.e. ``XLinks``)\n\nMotivation\n----------\n\nOn `Expressions: Known issues / remaining tasks \u003chttps://wiki.freecadweb.org/Expressions#Known_issues_.2F_remaining_tasks\u003e`_, it's mentioned:\n\n    There is no expression manager implemented where all expressions in a document are listed, and can be created, deleted, queried, etc.\n\nLarge complex FreeCAD projects typically rely on extensive use of cross-document referencing to properties such as aliases in spreadsheets.\n\nWhen you have dozens of references to the same property, it becomes very difficult to find all the places where references exist or rename the property.\n\n``fcxref`` aims to fill this gap until similiar functionality can be added to FreeCAD core.\n\nSee the following related FreeCAD forum discussions for additional motivation:\n\n* `Expression engine - Automatic renaming \u003chttps://forum.freecadweb.org/viewtopic.php?t=18049\u003e`_\n* `Rename a file containing external links \u003chttps://forum.freecadweb.org/viewtopic.php?p=471267\u003e`_\n\nApproach\n--------\n``fcxref`` relies on parsing the ``Document.xml`` in compressed ``.FCStd`` files.\n\nInstallation\n------------\n\nAvailable on the `Python Package Index (PyPI) \u003chttps://pypi.org/project/fcxref/\u003e`_.\n\n.. code-block::\n\n   pip install fcxref\n\nUsage\n-----\nThere are two ways to use ``fcxref``:\n\n1. via the Python API\n2. vai the Command Line\n\nThe following 2 sections cover these 2 usage methods with documents in the ``example/`` directory.\n\nConsider you have a ``MainDocument.FCStd`` containing a spreadsheet that drives your model,\nand ``ExampleDocument.FCStd`` that references aliases in that spreadsheet.\n\nPython API\n----------\n\nfind\n^^^^\n\n.. code-block:: python\n\n   from fcxref import find, Query\n   \n   base_path = './example'\n   references = find(base_path, Query('MainDocument', 'Spreadsheet', 'Value'))\n   print('\\n'.join(map(str, references)))\n\n.. code-block::\n\n   MainDocument Spreadsheet.A1 'Value content indirect\n   MainDocument Spreadsheet.B1 Value alias source\n   MainDocument Spreadsheet.B2 =Value content indirect\n   MainDocument Box.Height Cylinder.Value expression indirect\n   MainDocument Box.Length Spreadsheet.Value expression indirect\n   MainDocument Box.Width \u003c\u003cSpreadsheet\u003e\u003e.Value expression indirect\n   ExampleDocument Spreadsheet.B1 =MainDocument#Spreadsheet.Value content direct\n   ExampleDocument Spreadsheet.A1 'Value content indirect\n   ExampleDocument Spreadsheet.B1 Value alias indirect\n   ExampleDocument Box.Length Spreadsheet.Value expression indirect\n\n\nrename\n^^^^^^\n\nThe ``rename_property`` function takes:\n\n1. the base path to look for FreeCAD documents in\n2. the name or label of the document\n3. the name or label of the object\n4. and a 2-element tuple containing the property before and after renaming. \n\nIt returns a dictionary where keys are filepaths to updated ``.FCStd`` files,\nand values are XML `Element`_ objects representing updated ``Document.xml`` files.\n\n.. _Element: https://docs.python.org/3/library/xml.etree.elementtree.html#xml.etree.ElementTree.Element\n\n.. code-block:: python\n\n   from fcxref import rename_property\n   \n   base_path = './example'\n   root_by_document_path = rename_property(base_path, 'MainDocument', 'Spreadsheet', ('Value', 'RenamedValue'))\n   print(root_by_document_path)\n\n.. code-block::\n\n   {'ExampleDocument.FCStd': \u003cElement 'Document' at 0x7efcd281cc20\u003e, 'MainDocument.FCStd': \u003cElement 'Document' at 0x7f4d13c39270\u003e}\n\nremove\n^^^^^^\n\nThe ``remove`` function takes:\n\n1. the base path to look for FreeCAD documents in\n2. the name of the document (**label is not supported**)\n\nIt returns a dictionary where keys are filepaths to updated ``.FCStd`` files,\nand values are XML `Element`_ objects representing updated ``Document.xml`` files.\n\n.. code-block:: python\n\n   from fcxref import remove\n   \n   base_path = './example'\n   root_by_document_path = remove(base_path, 'MainDocument')\n   print(root_by_document_path)\n\n.. code-block::\n\n   {'ExampleDocument.FCStd': \u003cElement 'Document' at 0x7efcd281cc20\u003e}\n\nCommand Line\n------------\nUpon `installing \u003c#installation\u003e`_ ``fcxref``, the ``fcxref`` command will become globally accessible.\n\nFor usage information, pass ``--help`` to each command.\n\nEach command scans for ``*.FCStd`` files recursively from the current working directory.\n\nThus, you should navigate to a directory where you store your FreeCAD documents before executing ``fcxref`` commands.\n\n.. code-block::\n\n   $ fcxref --help ↵\n   usage: fcxref [-h] [--version] {find,rename,remove} ...\n   \n   Manage cross-document references to properties.\n   \n   optional arguments:\n     -h, --help            show this help message and exit\n     --version             show program's version number and exit\n   \n   Commands:\n     {find,rename,remove}\n       find                Find cross-document references to an object or property\n       rename              Rename cross-document references to a property\n       remove              Remove XLinks to specified document\n\nfind\n^^^^\n\n.. code-block::\n\n   $ fcxref find --help ↵                \n   usage: fcxref find \u003cdocument\u003e \u003cobject\u003e [property]\n   \n   Surround arguments containing special characters in quotes (e.g. \"\u003c\u003cMy Label\u003e\u003e\").\n   \n   positional arguments:\n     document    Document name or label.\n     object      Object name or label.\n     property    Property.\n   \n   optional arguments:\n     -h, --help  show this help message and exit\n\nSimple Queries\n\"\"\"\"\"\"\"\"\"\"\"\"\"\"\n\n.. code-block::\n   \n   $ fcxref find MainDocument Spreadsheet Value ↵\n   MainDocument Spreadsheet.A1 'Value content indirect\n   MainDocument Spreadsheet.B1 Value alias source\n   MainDocument Spreadsheet.B2 =Value content indirect\n   MainDocument Box.Height Cylinder.Value expression indirect\n   MainDocument Box.Length Spreadsheet.Value expression indirect\n   MainDocument Box.Width \u003c\u003cSpreadsheet\u003e\u003e.Value expression indirect\n   ExampleDocument Spreadsheet.B1 =MainDocument#Spreadsheet.Value content direct\n   ExampleDocument Spreadsheet.A1 'Value content indirect\n   ExampleDocument Spreadsheet.B1 Value alias indirect\n   ExampleDocument Box.Length Spreadsheet.Value expression indirect\n\n💡 **TIP:** When using special characters on the command line such as ``\u003c`` and ``\u003e`` for label names, surround the argument in double-quotes.\n\nrename\n^^^^^^\n\n.. code-block::\n\n   $ fcxref rename --help ↵\n   usage: fcxref rename \u003cdocument\u003e \u003cobject\u003e \u003cfrom_property\u003e \u003cto_property\u003e\n   \n   Surround arguments containing special characters in quotes (e.g. \"\u003c\u003cMy Label\u003e\u003e\").\n   \n   positional arguments:\n     document       Document name or label of reference to rename.\n     object         Object name or label of reference to rename.\n     from_property  Property of reference before renaming.\n     to_property    Property of reference after renaming.\n   \n   optional arguments:\n     -h, --help     show this help message and exit\n\n\nSimple Renames\n\"\"\"\"\"\"\"\"\"\"\"\"\"\"\n\nThe ``rename`` command will prompt users for confirmation before modifying any files,\nand defaults to \"No\" if an explicit \"Yes\" is not provided.\n\n.. code-block::\n\n   $ fcxref rename MainDocument Spreadsheet Value RenamedValue ↵\n   The following 2 document(s) reference MainDocument#Spreadsheet.Value:\n     ExampleDocument.FCStd\n     MainDocument.FCStd\n   \n   Do you wish to rename references to MainDocument#Spreadsheet.RenamedValue? [y/N] \n   y ↵\n   2 document(s) updated.\n\nremove\n^^^^^^\n\n.. code-block::\n\n   $ fcxref remove --help ↵\n   usage: fcxref remove \u003cdocument\u003e\n   \n   Surround arguments containing special characters in quotes (e.g. \"\u003c\u003cMy Label\u003e\u003e\").\n   \n   positional arguments:\n     document    Document name of XLinks to remove.\n   \n   optional arguments:\n     -h, --help  show this help message and exit\n\nSimple Removals\n\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\n\nThe ``remove`` command will prompt users for confirmation before modifying any files,\nand defaults to \"No\" if an explicit \"Yes\" is not provided.\n\n.. code-block::\n\n   $ fcxref remove MainDocument ↵\n   The following 1 document(s) contain XLinks to MainDocument:\n     example/ExampleDocument.FCStd\n\n   Do you wish to remove XLinks to MainDocument? (this will break document linking) [y/N] \n   y ↵\n   1 document(s) updated.\n\nSupported FreeCAD Versions\n--------------------------\nCurrently only FreeCAD 1.0 and greater is supported.\n\nIf changes are minimal, then supporting older versions may be considered.\n\nChangelog\n---------\nSee `Changelog \u003c./CHANGELOG.rst\u003e`__.\n\nContributing\n------------\nSee `Contributing Guidelines \u003c./CONTRIBUTING.rst\u003e`_.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgbroques%2Ffcxref","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgbroques%2Ffcxref","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgbroques%2Ffcxref/lists"}