{ "info": { "author": "Ian Epperson", "author_email": "ian@epperson.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 3 - Alpha", "Environment :: Other Environment", "Intended Audience :: Developers", "License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)", "Operating System :: OS Independent", "Programming Language :: Python", "Topic :: Internet :: WWW/HTTP :: Site Management", "Topic :: Office/Business :: Groupware", "Topic :: Software Development :: Libraries :: Python Modules", "Topic :: Utilities" ], "description": "pyredminews\n===========\n\nPython Redmine Web Services Library\n\nThis python library facilitates creating, reading, updating and deleting content from a Redmine_ installation through the REST API.\n\nCommunications are performed via HTTP/S, freeing up the need for the Python script to run on the same machine as the Redmine installation.\n\nThis library was originally published at http://code.google.com/p/pyredminews/\n\n.. _Redmine: http://www.redmine.org/\n\nInstallation\n------------\n\nPyPI\n++++\n\nThe easiest way to install. The module is available on the Python Package Index (PyPI) and is available for the \neasy_install or pip commands. easy_install is available by default on OSX, either command may be available for whatever\nflavor of Unix you are using, and must be installed on Windows.\n\n::\n\n > easy_install pyredmine\n \n::\n\n > pip install pyredmine\n\n \nGitHub\n++++++\n\nTo get the latest code updates or to get a different version of the library, you can clone this Github repository\nand run the setup script manually.\n\n::\n\n > git clone https://github.com/ianepperson/pyredminews.git\n > cd pyredminews\n > python setup.py\n \n\nHow to use it\n-------------\n\nSet up Redmine\n++++++++++++++\n\nWithin Redmine, you must enable the REST web service before most of the library operations will work.\nIn the Administration -> Settings page on the Authentication tab, check the box for\n\"Enable REST web service\" and click the Save button. If the REST interface is not enabled, the users\nwill not see an \"API key\" in their user information page.\nMany of the read-only actions provided by this library will still work, but the write/create operations will fail.\n\nDocumentation\n+++++++++++++\n\nThe library, like most good Python libraries, is self documenting. In the console, import the library then type ''help(redmine)'' \nfor all the details.\n\nStep by Step\n------------\n\nStart Python, Import the Module\n+++++++++++++++++++++++++++++++\n\nOpen a Python terminal window. \n\n::\n\n $ python\n Python 2.6.1 (r261:67515, Feb 11 2010, 00:51:29) \n [GCC 4.2.1 (Apple Inc. build 5646)] on darwin\n Type \"help\", \"copyright\", \"credits\" or \"license\" for more information.\n >>> \n\nNow, import the Redmine class\n\n::\n\n >>> from redmine import Redmine\n >>>\n\nView the documentation\n++++++++++++++++++++++\n\n::\n\n >>> help(Redmine)\n Help on class Redmine in module redmine.redmine:\n class Redmine\n | Class to interoperate with a Redmine installation using the REST web services.\n | instance = Redmine(url, [key=strKey], [username=strName, password=strPass] )\n | \n | url is the base url of the Redmine install ( http://my.server/redmine )\n (type q to quit)\n\netc.\n\nLocate a Redmine installation\n+++++++++++++++++++++++++++++\n\nIf you don't have Redmine installed somewhere that you can play with you can use the public demo server. \nWith your web browser, go take a look at http://demo.redmine.org. Find or make a project and note its identifier \n(not its pretty name, but the path it ends up in such as \"testproject\" in ``http://demo.redmine.org/projects/testproject``). \nMake a bug and note its number. The remaining examples will assume you've done this.\n\nCurrently the Redmine instalation running at demo.redmine.org *does not* have the REST interface enabled. \n\nSet up the Connection\n+++++++++++++++++++++\n\nMake an instance that represents the server you want to connect to.\n\n::\n\n >>> demo_anon = Redmine('http://demo.redmine.org')\n >>>\n\n\nAuthentication\n++++++++++++++\n\nYou can perform most of the view actions with this anonymous access, but for the cool stuff, \nyou should register an account and set up that access:\n\n::\n\n >>> demo = Redmine('http://demo.redmine.org', username='pyredmine', password='password')\n >>>\n\n\nSince leaving around your password in a script really sucks, Redmine allows you to use a user API key instead. \nOnce logged into Redmine, on the My Account page, click on the Show button under the API Access Key on the right. \nThat will reveal a key that can be used instead of a username/password. If you do not see any reference to the\nAPI key in the right-hand panel, the REST interface probably hasn't been enabled - see `Set up Redmine`_ above.\n\n::\n\n >>> demo = Redmine('http://demo.redmine.org', key='701c0aec4330fb2f1db944f1808e1e987050c7f5')\n >>>\n\n\nDefine the Redmine Version\n++++++++++++++++++++++++++\n\nDifferent versions of Redmine can use improved security, and have different items available through the REST interface.\nIn order for the module to correctly represent the data and use available security features, you should tell\nthe object what version your Redmine server is using.\n\n::\n\n >>> demo = Redmine('http://demo.redmine.org', username='pyredmine', password='password', version=2.1)\n >>>\n\n\n\nView Project Data\n+++++++++++++++++\n\nAlthough you can use this library to look up a large list of projects, the easiest helper functions are designed \nto work with a single project of a given identifier (testproject, in our example above). The projects parameter on\nthe Redmine object can be used to return a single Project object. \n\n::\n\n >>> project = demo.projects['demoproject']\n >>> \n\nNow with that shiny new project object, you can take a look at the data available:\n\n::\n\n >>> project.id\n 393\n >>> project.identifier\n u'demoproject'\n >>> \n\nThe fields available on the project will differ depending on the version of Redmine.\nTo see the full list of items available for the project, try:\n\n::\n\n >>> dir(project)\n (politely ignore anything staring with a _)\n u'created_on',\n u'description',\n u'homepage',\n u'id',\n u'identifier',\n 'issues',\n u'name',\n 'parent',\n 'refresh',\n 'save',\n 'time_entries',\n u'updated_on']\n\n \n\nIf you happen to know the numeric ID of your project, that can also be used to look it up. If demoproject is in fact\nid 393, then the following will return the same project:\n\n::\n\n >>> project = demo.projects[393]\n \nChange the Project\n++++++++++++++++++\n\nChanging the fields of the project are as easy as changing the objects parameters and invoking the save method.\n\n::\n\n >>> project.homepage = 'http://www.dead-parrot.com'\n >>> project.name = 'Dead Parrot Society'\n >>> project.save()\n \nIf you try and set a parameter for a read-only field, you'll get an attribute error.\n\n::\n\n >>> project.updated_on = 'today'\n AttributeError: Can't set attribute updated_on.\n \nIf your Redmine instance has custom fields set for projects, those fields and their values will be returned and can be changed\nin the same manner:\n\n::\n\n >>> project.custom_fields['Customer'] = 'John Cleese'\n >>> project.save()\n \n\nExamine All Projects\n++++++++++++++++++++\n\nThe projects member can be iterated over to retrieve information about all projects. Be default, Redmine will return 25 items\nat a time, so the following query might take some time to complete.\n\n::\n\n >>> for proj in demo.projects:\n ... print \"%s : %s\" % (proj.name, proj.homepage)\n \n (truncated)\n Test Project LS II : None\n Test Project Only : None\n Test Project Rizal : None\n Create home page : None\n Test Project SES : None\n Test project SGO : None\n Test Project Trial : None\n Test Project Tutorial ABCDE : None\n \n\nGet All Issues for a Project\n++++++++++++++++++++++++++++\n\nThe issues associated for a project can be retreived by iterating over the 'issues' method in a project.\n\n::\n\n >>> for issue in project.issues:\n ... print issue\n \n \n \n (truncated)\n \n(You may get an Unicode error if any of the issues has unicode in the subject. If you do, instead use: print \"%s\" % issue )\n\nIf you want to exclude issues from any subprojects, you can add query parameters to the iterator:\n\n::\n\n >>> for issue in project.issues(subproject_id='!*'):\n ... print issue\n \nOther parameters are:\n\n* tracker_id: get issues from the tracker with the given id\n* status_id: get issues with the given status id only. Possible values: open, closed, * to get open and closed issues, status id\n* assigned_to_id: get issues which are assigned to the given user id\n* cf_x: get issues with the given value for custom field with an ID of x. (Custom field must have 'used as a filter' checked.)\n\n\nCreate a New Issue\n++++++++++++++++++\n\nYou can use the project object to create a new issue for that project:\n\n::\n\n >>> issue = project.issues.new(subject=\"Test from Python\", description=\"That rabbit is dynamite!\")\n >>> issue.id\n 35178\n >>> issue.created_on\n datetime.datetime(2013, 2, 7, 1, 0, 28, tzinfo=tzutc())\n >>>\n\nNote that the new command returned an Issue object containing all (or, on older Redmine versions, most) of the new issue's data. \nYou can now go to http://demo.redmin.org/projects/demoproject/issues to see your new issue. Any date/time information is returned\nas a `Python datetime object `_.\n(Note the issue ID, you'll need that for the next steps)\n\nView an Issue\n+++++++++++++\n\nYou can view any issue by its ID:\n\n::\n\n >>> issue = demo.issues[35178]\n >>> issue.status\n \n >>> issue.subject\n u'That rabbit is dynamite!'\n\nLike the issues.new command above, it's returning an object with all of the issue data. \nNote that this command is not running from the Project object but from the Redmine object.\n\nIf you examine your issue object, you'll see that it contains an author parameter, which is itself another object:\n\n::\n\n >>> issue.author\n \n\nHowever, this user object is incomplete:\n\n::\n\n >>> issue.author.last_login\n \n >>>\n\npyRedmine created the object with the data it had on hand, and since it doesn't have the last_login data (it wasn't\nin the issue information) it isn't shown here. There are two ways to flesh out that data, one is to use the refresh\nmethod for the author (works on Redmine 1.1 and later where this data is available).\n\n::\n\n >>> issue.author.refresh()\n >>> issue.author.last_login\n datetime.datetime(2013, 2, 7, 1, 0, 28, tzinfo=tzutc())\n \nThe other is to simply request that user id from the server\n\n::\n\n >>> demo.users[5]\n \n >>> issue.author.last_login\n datetime.datetime(2013, 2, 7, 1, 0, 28, tzinfo=tzutc())\n\npyRedmine caches all objects it sees and sets up all cross references. Updating a Redmine object attached to one object \nwill update them all. Also, this allows you to directly compare objects if needed:\n\n::\n\n >>> issue.author == issue.assigned_to\n True \n\nChange an Issue's Status\n++++++++++++++++++++++++\n\nYou can move an issue through the workflow as well. You must set an issue status based on the status ID,\nwhich is can only be discovered in Redmine version 2.2 and later (but not yet available via this library).\nBy default, the library uses the status ID for Resolved and Closed from a default Redmine installation, \nbut if you've changed them in the Administration page, you'll have to change these each time as well.\n\n::\n\n >>> demo.ISSUE_STATUS_ID_RESOLVED\n 3\n >>> demo.ISSUE_STATUS_ID_CLOSED\n 5\n \n\nThe closed and resolved methods are available on the issue itself, with an optional comment:\n\n::\n\n >>> issue.close('Closed the issue from Python!')\n >>> issue.resolve('Resolved the issue from Python!')\n \nSome versions of Redmine will not return an error if this operation fails, so be careful of false hopes.\n\nIf you need to set another status, you'll need to find the requisite status ID, then use the set_status method\n(again, with optional comment):\n\n::\n\n >>> issue.set_status(8, 'Setting the status from Python!')\n\nIf you need to close an issue and don't need to get an issue object, you can set the issue status directly\nusing the Redmine server object with a single operation:\n\n::\n\n >>> demo.issues.update(35178, status_id=5)\n \n\nChange an Issue\n+++++++++++++++\n\nJust like with projects, to change a field on an issue simply change the parameter on the issue object\nthen invoke the save method.\n\n::\n\n >>> issue.description = \"The parrot doesn't seem to be alive.\"\n >>> issue.save()\n \nIf your installation of Redmine has custom fields on issues, those fields can be inspected and set.\n\n::\n\n >>> issue.custom_fields['Inform the client']\n u'0'\n >>> issue.custom_fields['Inform the client'] = 1\n >>> issue.save()\n \n\nIf you want to change the project this issue is assigned to, you can set it directly to either a project object\nor a numeric project ID, then save it.\n\n::\n\n >>> issue.project = 12\n >>> issue.save()\n \n >>> issue.project = demo.projects['test']\n >>> issue.save()\n\n\nDelete an Issue\n+++++++++++++++\n\nThere is also an issue delete command that you should use with care. In a real production environment, \nyou normally would never delete an issue - just leave it closed. Deleting it will remove history, time worked, \nand almost every trace of it. So, be careful! On the demo server, you don't have permission to delete, so go ahead and try:\n\n::\n\n >>> demo.issues.delete(35178)\n (whole lot of response, including)\n urllib2.HTTPError: HTTP Error 403: Forbidden\n >>>\n\nDifferent versions of Redmine are inconsistent about when they returns 403 and when they just doesn't work. You can't rely on the lack of an \nHTTPError to guarantee success.\n\nNote that there is no good method to assign an issue to a user. You can assign to the numeric user ID, \nbut there's no interface yet for looking up the ID based on a user name. You can use the catch-all \ncommand updateIssueFromDict to assign the issue to user number 25:\n\n::\n\n >>> demo.updateIssueFromDict(35178, {'assigned_to_id':'25'} )\n http://demo.redmine.org/issues/35178.xml\n ''\n\nOther Objects\n+++++++++++++\n\nDepending on what Redmine version you have, you can use these same commands to get/update/delete different Redmine items:\n\n* users\n* news\n* time_entries\n\nNot every item supports every method. For instance, no current version of Redmine allows creating a news item, thus:\n\n::\n\n >>> demo.news.new(title='does this work?', description='Nope', author_id=4)\n AttributeError: new is not available for News", "description_content_type": null, "docs_url": null, "download_url": "UNKNOWN", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/ianepperson/pyredminews", "keywords": "redmine,server", "license": "UNKNOWN", "maintainer": null, "maintainer_email": null, "name": "pyredmine", "package_url": "https://pypi.org/project/pyredmine/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/pyredmine/", "project_urls": { "Download": "UNKNOWN", "Homepage": "https://github.com/ianepperson/pyredminews" }, "release_url": "https://pypi.org/project/pyredmine/0.2.4/", "requires_dist": null, "requires_python": null, "summary": "Python Redmine Web Services Library", "version": "0.2.4" }, "last_serial": 797674, "releases": { "0.2": [ { "comment_text": "", "digests": { "md5": "cdc717b4edcd7859a6610273bac3fca6", "sha256": "809a9fc9faaaa0f6d0ad2392f46f7ea5a09269c2ccf59298513b666f3d3762e5" }, "downloads": -1, "filename": "pyredmine-0.2.tar.gz", "has_sig": false, "md5_digest": "cdc717b4edcd7859a6610273bac3fca6", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 18252, "upload_time": "2013-02-07T05:30:39", "url": "https://files.pythonhosted.org/packages/59/81/06f49fde140d817d625ead0e810a84c77fb93e5d2c337cfd4ebb943a2376/pyredmine-0.2.tar.gz" } ], "0.2.1": [ { "comment_text": "", "digests": { "md5": "c1571ef13230a32fedcd2b7226222ecd", "sha256": "8f5a6afbcccf96c5dd7e4a88ddf1f1443ced6485fe0479b36d7e9e2d00f7c1ea" }, "downloads": -1, "filename": "pyredmine-0.2.1.tar.gz", "has_sig": false, "md5_digest": "c1571ef13230a32fedcd2b7226222ecd", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 30492, "upload_time": "2013-02-07T05:43:55", "url": "https://files.pythonhosted.org/packages/54/8f/3d57780f39e7f9bce727088e3c122db301be57cfffbd9d4d32a3554e2eeb/pyredmine-0.2.1.tar.gz" } ], "0.2.2": [ { "comment_text": "", "digests": { "md5": "2b9cedb4f7accb9c3d66ff1570adf635", "sha256": "24597547c048cedf502ef67f7ad7dde5ed26d195139e53618d30603283a4e1d8" }, "downloads": -1, "filename": "pyredmine-0.2.2.tar.gz", "has_sig": false, "md5_digest": "2b9cedb4f7accb9c3d66ff1570adf635", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 30496, "upload_time": "2013-02-07T06:01:53", "url": "https://files.pythonhosted.org/packages/57/a3/98571b6fa48c94e7b9f4c00b8649ef51836bbf87b449d72a3e26f1b26fa5/pyredmine-0.2.2.tar.gz" } ], "0.2.3": [ { "comment_text": "", "digests": { "md5": "e80dca086fbc1e196436410725ab8169", "sha256": "e277f11d23b44192032bd100ca86ea719afe4a2c721bd09c0dfe36651e879d95" }, "downloads": -1, "filename": "pyredmine-0.2.3.tar.gz", "has_sig": false, "md5_digest": "e80dca086fbc1e196436410725ab8169", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 31124, "upload_time": "2013-02-07T06:06:36", "url": "https://files.pythonhosted.org/packages/7c/f6/8b48d822c3f3093fc9a0627072fc044bae80044b09200fb493e77bd12e13/pyredmine-0.2.3.tar.gz" } ], "0.2.4": [ { "comment_text": "", "digests": { "md5": "a4504b3401485e3236ec2eb6327160f6", "sha256": "7b76fdc57577e8b58be47ae0e84ac272759ba0ae8180742628c5d288835a9ba8" }, "downloads": -1, "filename": "pyredmine-0.2.4.tar.gz", "has_sig": false, "md5_digest": "a4504b3401485e3236ec2eb6327160f6", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 35856, "upload_time": "2013-02-07T06:08:27", "url": "https://files.pythonhosted.org/packages/89/aa/9b272c2e967ca676798441da007820d18f90f8f73117959c1cebec4ac437/pyredmine-0.2.4.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "a4504b3401485e3236ec2eb6327160f6", "sha256": "7b76fdc57577e8b58be47ae0e84ac272759ba0ae8180742628c5d288835a9ba8" }, "downloads": -1, "filename": "pyredmine-0.2.4.tar.gz", "has_sig": false, "md5_digest": "a4504b3401485e3236ec2eb6327160f6", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 35856, "upload_time": "2013-02-07T06:08:27", "url": "https://files.pythonhosted.org/packages/89/aa/9b272c2e967ca676798441da007820d18f90f8f73117959c1cebec4ac437/pyredmine-0.2.4.tar.gz" } ] }