Merge pull request #46 from danyeaw/merge-gitlab

Merge gitlab updates
This commit is contained in:
Dan Yeaw 2018-01-13 18:43:26 -05:00 committed by GitHub
commit 9c314a4203
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
323 changed files with 9523 additions and 4435 deletions

2
.gitignore vendored
View File

@ -6,3 +6,5 @@ po/gaphor.pot
html
*.swp
*.egg
env
*.bak

7
.mailmap Normal file
View File

@ -0,0 +1,7 @@
Adam Boduch <adam.boduch@gmail.com> <adam@adam-laptop.(none)>
Adam Boduch <adam.boduch@gmail.com> <adam@enomaly.com>
Adam Boduch <adam.boduch@gmail.com> adamboduch <adam.boduch@gmail.com>
Adam Boduch <adam.boduch@gmail.com> adamboduch <adam@adam-laptop.(none)>
Dan Yeaw <dan@yeaw.me> danyeaw <danyeaw@gmail.com>
Artur Wroblewski <wrobell@pld-linux.org> wrobell <wrobell@pld-linux.org>
Enno Groeper <enno@groeper-berlin.de> Enno Gröper <enno@groeper-berlin.de>

27
.update-copyright.conf Normal file
View File

@ -0,0 +1,27 @@
[project]
name: Gaphor
vcs: Git
[files]
authors: yes
files: yes
ignored: LICENSE.txt | README.rst | .update-copyright.conf | .git* | *.md | *.txt | MANIFEST.in | NEWS | gaphor.desktop | pylintc | pygtk.vext | tox.ini
pyfile: /home/dan/Code/update-copyright-0.6.2/update_copyright/license.py
[copyright]
short: {project} comes with ABSOLUTELY NO WARRANTY and is licensed under the GNU Library General Public License.
long: This file is part of {project}.
{project} is free software: you can redistribute it and/or modify
it under the terms of the GNU Library General Public License
as published by the Free Software Foundation, either version 2 of
the License, or (at your option) any later version.
{project} is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Library General Public License for more details.
You should have received a copy of the GNU General Public License
along with {project}. If not, see <http://www.gnu.org/licenses/>.

16
AUTHORS
View File

@ -1,3 +1,15 @@
Arjan Molenaar <a.molenaar@yirdis.nl>
Gaphor was written by:
Adam Boduch <adam.boduch@gmail.com>
Alexis Howells <al@aejh.co.uk>
Antonin Delpeuch <wetneb@gmail.com>
Antony N. Pavlov <antony@niisi.msk.ru>
Arjan Molenaar <gaphor@gmail.com>
Artur Wroblewski <wrobell@pld-linux.org>
Jeroen Vloothuis <jeroen@vloothuis.net>
Christian Hoff <christian_hoff@gmx.net>
Dan Yeaw <dan@yeaw.me>
Encolpe DEGOUTE <encolpe@colpi.org>
Enno Groeper <enno@groeper-berlin.de>
Jordi Mallach <jordi@sindominio.net>
Ygor Mutti <mamutti@icaju.com>
slmm <noreply@example.com>
syt <noreply@example.com>

46
CODE_OF_CONDUCT.md Normal file
View File

@ -0,0 +1,46 @@
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at dan@yeaw.me. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
[homepage]: http://contributor-covenant.org
[version]: http://contributor-covenant.org/version/1/4/

View File

@ -3,31 +3,14 @@ Feel free to hack Gaphor. Patches are welcome.
Fetching Development Dependencies
=================================
Gaphor uses Easy Install to manage in easy way its dependencies.
To fetch and install dependencies as non-root user
1. Create ~/.pydistutils.cfg file
[install]
install_lib = ~/opt/share/python2.5/site-packages
install_scripts = ~/opt/bin
2. Create (or extend) PYTHONPATH variable
export PYTHONPATH=~/opt/share/python2.5/site-packages
3. Run setup.py script to fetch and install dependencies
python setup.py develop
Prefix ~/opt can be changed to something more suitable for your setup.
Above is based on
http://peak.telecommunity.com/DevCenter/EasyInstall#traditional-pythonpath-based-installation
Gaphor uses pip to manage in easy way its dependencies.
To fetch and install dependencies as non-root user:
In Linux recommend using a virtual environment for installation. Since pyGTK doesn't work well with a virtualenv,
install it outside the virtual environment and then start your the virtualenv using the --system-site-packages option:
$ virtualenv --system-site-packages venv
$ source venv/bin/activate
$ pip install gaphor
Running Tests
=============
@ -64,4 +47,3 @@ The user interface. This is where most of the work is to be done.
misc
----
Some utility stuff, such as Actions and aspects are put in here.

View File

@ -1,482 +1,482 @@
GNU LIBRARY GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1991 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the library GPL. It is
numbered 2 because it goes with version 2 of the ordinary GPL.]
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Library General Public License, applies to some
specially designated Free Software Foundation software, and to any
other libraries whose authors decide to use it. You can use it for
your libraries, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if
you distribute copies of the library, or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link a program with the library, you must provide
complete object files to the recipients so that they can relink them
with the library, after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
Our method of protecting your rights has two steps: (1) copyright
the library, and (2) offer you this license which gives you legal
permission to copy, distribute and/or modify the library.
Also, for each distributor's protection, we want to make certain
that everyone understands that there is no warranty for this free
library. If the library is modified by someone else and passed on, we
want its recipients to know that what they have is not the original
version, so that any problems introduced by others will not reflect on
the original authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that companies distributing free
software will individually obtain patent licenses, thus in effect
transforming the program into proprietary software. To prevent this,
we have made it clear that any patent must be licensed for everyone's
free use or not licensed at all.
Most GNU software, including some libraries, is covered by the ordinary
GNU General Public License, which was designed for utility programs. This
license, the GNU Library General Public License, applies to certain
designated libraries. This license is quite different from the ordinary
one; be sure to read it in full, and don't assume that anything in it is
the same as in the ordinary license.
The reason we have a separate public license for some libraries is that
they blur the distinction we usually make between modifying or adding to a
program and simply using it. Linking a program with a library, without
changing the library, is in some sense simply using the library, and is
analogous to running a utility program or application program. However, in
a textual and legal sense, the linked executable is a combined work, a
derivative of the original library, and the ordinary General Public License
treats it as such.
Because of this blurred distinction, using the ordinary General
Public License for libraries did not effectively promote software
sharing, because most developers did not use the libraries. We
concluded that weaker conditions might promote sharing better.
However, unrestricted linking of non-free programs would deprive the
users of those programs of all benefit from the free status of the
libraries themselves. This Library General Public License is intended to
permit developers of non-free programs to use free libraries, while
preserving your freedom as a user of such programs to change the free
libraries that are incorporated in them. (We have not seen how to achieve
this as regards changes in header files, but we have achieved it as regards
changes in the actual functions of the Library.) The hope is that this
will lead to faster development of free libraries.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, while the latter only
works together with the library.
Note that it is possible for a library to be covered by the ordinary
General Public License rather than by this special one.
GNU LIBRARY GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library which
contains a notice placed by the copyright holder or other authorized
party saying it may be distributed under the terms of this Library
General Public License (also called "this License"). Each licensee is
addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation
and installation of the library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also compile or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
c) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
d) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the source code distributed need not include anything that is normally
distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License may add
an explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded. In such case, this License incorporates the limitation as if
written in the body of this License.
13. The Free Software Foundation may publish revised and/or new
versions of the Library General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Libraries
If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
everyone can redistribute and change. You can do so by permitting
redistribution under these terms (or, alternatively, under the terms of the
ordinary General Public License).
To apply these terms, attach the following notices to the library. It is
safest to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.
<one line to give the library's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the
Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307 USA.
Also add information on how to contact you by electronic and paper mail.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the library, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
<signature of Ty Coon>, 1 April 1990
Ty Coon, President of Vice
That's all there is to it!
GNU LIBRARY GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1991 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the library GPL. It is
numbered 2 because it goes with version 2 of the ordinary GPL.]
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Library General Public License, applies to some
specially designated Free Software Foundation software, and to any
other libraries whose authors decide to use it. You can use it for
your libraries, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if
you distribute copies of the library, or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link a program with the library, you must provide
complete object files to the recipients so that they can relink them
with the library, after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
Our method of protecting your rights has two steps: (1) copyright
the library, and (2) offer you this license which gives you legal
permission to copy, distribute and/or modify the library.
Also, for each distributor's protection, we want to make certain
that everyone understands that there is no warranty for this free
library. If the library is modified by someone else and passed on, we
want its recipients to know that what they have is not the original
version, so that any problems introduced by others will not reflect on
the original authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that companies distributing free
software will individually obtain patent licenses, thus in effect
transforming the program into proprietary software. To prevent this,
we have made it clear that any patent must be licensed for everyone's
free use or not licensed at all.
Most GNU software, including some libraries, is covered by the ordinary
GNU General Public License, which was designed for utility programs. This
license, the GNU Library General Public License, applies to certain
designated libraries. This license is quite different from the ordinary
one; be sure to read it in full, and don't assume that anything in it is
the same as in the ordinary license.
The reason we have a separate public license for some libraries is that
they blur the distinction we usually make between modifying or adding to a
program and simply using it. Linking a program with a library, without
changing the library, is in some sense simply using the library, and is
analogous to running a utility program or application program. However, in
a textual and legal sense, the linked executable is a combined work, a
derivative of the original library, and the ordinary General Public License
treats it as such.
Because of this blurred distinction, using the ordinary General
Public License for libraries did not effectively promote software
sharing, because most developers did not use the libraries. We
concluded that weaker conditions might promote sharing better.
However, unrestricted linking of non-free programs would deprive the
users of those programs of all benefit from the free status of the
libraries themselves. This Library General Public License is intended to
permit developers of non-free programs to use free libraries, while
preserving your freedom as a user of such programs to change the free
libraries that are incorporated in them. (We have not seen how to achieve
this as regards changes in header files, but we have achieved it as regards
changes in the actual functions of the Library.) The hope is that this
will lead to faster development of free libraries.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, while the latter only
works together with the library.
Note that it is possible for a library to be covered by the ordinary
General Public License rather than by this special one.
GNU LIBRARY GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library which
contains a notice placed by the copyright holder or other authorized
party saying it may be distributed under the terms of this Library
General Public License (also called "this License"). Each licensee is
addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation
and installation of the library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also compile or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
c) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
d) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the source code distributed need not include anything that is normally
distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License may add
an explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded. In such case, this License incorporates the limitation as if
written in the body of this License.
13. The Free Software Foundation may publish revised and/or new
versions of the Library General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Libraries
If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
everyone can redistribute and change. You can do so by permitting
redistribution under these terms (or, alternatively, under the terms of the
ordinary General Public License).
To apply these terms, attach the following notices to the library. It is
safest to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.
<one line to give the library's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the
Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307 USA.
Also add information on how to contact you by electronic and paper mail.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the library, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
<signature of Ty Coon>, 1 April 1990
Ty Coon, President of Vice
That's all there is to it!

1
MANIFEST.in Normal file
View File

@ -0,0 +1 @@
include LICENSE.txt

4
NEWS
View File

@ -1,3 +1,7 @@
0.17.2
------
- Improved Python3 compatibility
0.17.1
------
- Added Russian translation

25
README
View File

@ -1,25 +0,0 @@
Gaphor - The Pythonic UML modelling tool
========================================
Gaphor is a UML modelling tool, written in Python. This makes it very easy to
use (and very easy to extend -- and to write ;-) ).
Install gaphor simply using easy-install:
$ easy-install gaphor
You can find the sources at GitHub:
http://github.com/amolenaar/gaphor/
For documentation refer to our project website:
http://gaphor.sourceforge.net/
Issue tracking is done at Lighthouse:
http://gaphor.lighthouseapp.com/
Have fun,
Gaphor development team

12
README.rst Normal file
View File

@ -0,0 +1,12 @@
Gaphor - The UML and SysML(soon!) Modeling Tool
===============================================
Gaphor is a free/libre/open source UML modeling tool, written in Python and licensed under the LGPLv2.
Install gaphor simply using pip:
$ pip install gaphor
For documentation refer to our project website:
http://gaphor.readthedocs.io

View File

View File

@ -1,100 +1,100 @@
Actions, menu items, toolbars and toolboxes
===========================================
The GTK+ structure is like this::
UIManager
|
ActionGroup
|
Action
The do_activate signal is emitted when an action is activated.
Where it should lead:
* Actions should be coded closer to the object their working on
- main actions - not dependent on GUI components (load/save/new/quit)
- main actions dependent on GUI component (sub-windows, console)
- Item actions, act either on a diagram, the selected or focused item
or no item.
- diagram actions (zoom, grid) work on active diagram (tab)
- menus and actions for diagram items through adapters
* Actions should behave more like adapters. E.g. when a popup menu is created
for an Association item, the menu actions should present themselves in the
context of that menu item (with toggles set right).
- Could be registered as adapters with a name.
* Each window has its own action group (every item with a menu?)
* One toplevel UIManager per window or one per application/gui_manager?
* Normal actions can be modeled as functions. If an action is sensitive or
visible depends on the state in the action. Hence we require the update()
method.
* create services for for "dynamic" menus (e.g. recent files/stereotypes)
Solution for simple actions
---------------------------
For an action to actually be useful a piece of menu xml is needed.
Hence an interface IActionProvider has to be defined::
class IActionProvider(interface.Interface):
menu_xml = interface.Attribute("The menu XML")
action_group = interface.Attribute("The accompanying ActionGroup")
Support for actions can be arranged by decorating actions with an :ref:`@action <action_doc>`
decorator and let the class create an ActionGroup using some
actionGroup factory function (no inheritance needed here).
Note that ActionGroup is a GTK class and should technically only be used in the
gaphor.ui package.
Autonom controllers can be defined, which provide a piece of functionality.
They can register handlers in order to update their state.
Maybe it's nice to configure those through the egg-info system. I suppose
gaphor.service will serve well (as they need to be initialized anyway)
* also inherit IActionProvider from IService?
::
[gaphor.services]
xx = gaphor.actions.whatever:SomeActionProviderClass
----
.. _action_doc:
.. autoclass:: gaphor.action.action
:members:
Solution for context sensitive menus
------------------------------------
Context sensitive menus, such as popup menus, should be generated and switched
on and off on demand.
Technically they should be enabled through services/action-providers.
It becomes even tougher when popup menus should act on parts of a diagram item
(such as association ends). This should be avoided. It may be a good idea to
provide such functionality through a special layer on the canvas, by means of
some easy clickable buttons around the "hot spot" (we already have something
like that for text around association ends).
Scheme:
1. User selects an item and presses the rigth mouse button: a popup menu
should be displayed.
2. Find the actual item (this may be a composite item of the element drawn).
Use an IItemPicker adapter for that (if no such interface is available,
use the item itself).
3. Find a IActionProvider adapters for the selected (focused) item.
4. Update the popup menu context (actions) for the selected item.
Actions, menu items, toolbars and toolboxes
===========================================
The GTK+ structure is like this::
UIManager
|
ActionGroup
|
Action
The do_activate signal is emitted when an action is activated.
Where it should lead:
* Actions should be coded closer to the object their working on
- main actions - not dependent on GUI components (load/save/new/quit)
- main actions dependent on GUI component (sub-windows, console)
- Item actions, act either on a diagram, the selected or focused item
or no item.
- diagram actions (zoom, grid) work on active diagram (tab)
- menus and actions for diagram items through adapters
* Actions should behave more like adapters. E.g. when a popup menu is created
for an Association item, the menu actions should present themselves in the
context of that menu item (with toggles set right).
- Could be registered as adapters with a name.
* Each window has its own action group (every item with a menu?)
* One toplevel UIManager per window or one per application/gui_manager?
* Normal actions can be modeled as functions. If an action is sensitive or
visible depends on the state in the action. Hence we require the update()
method.
* create services for for "dynamic" menus (e.g. recent files/stereotypes)
Solution for simple actions
---------------------------
For an action to actually be useful a piece of menu xml is needed.
Hence an interface IActionProvider has to be defined::
class IActionProvider(interface.Interface):
menu_xml = interface.Attribute("The menu XML")
action_group = interface.Attribute("The accompanying ActionGroup")
Support for actions can be arranged by decorating actions with an :ref:`@action <action_doc>`
decorator and let the class create an ActionGroup using some
actionGroup factory function (no inheritance needed here).
Note that ActionGroup is a GTK class and should technically only be used in the
gaphor.ui package.
Autonom controllers can be defined, which provide a piece of functionality.
They can register handlers in order to update their state.
Maybe it's nice to configure those through the egg-info system. I suppose
gaphor.service will serve well (as they need to be initialized anyway)
* also inherit IActionProvider from IService?
::
[gaphor.services]
xx = gaphor.actions.whatever:SomeActionProviderClass
----
.. _action_doc:
.. autoclass:: gaphor.action.action
:members:
Solution for context sensitive menus
------------------------------------
Context sensitive menus, such as popup menus, should be generated and switched
on and off on demand.
Technically they should be enabled through services/action-providers.
It becomes even tougher when popup menus should act on parts of a diagram item
(such as association ends). This should be avoided. It may be a good idea to
provide such functionality through a special layer on the canvas, by means of
some easy clickable buttons around the "hot spot" (we already have something
like that for text around association ends).
Scheme:
1. User selects an item and presses the rigth mouse button: a popup menu
should be displayed.
2. Find the actual item (this may be a composite item of the element drawn).
Use an IItemPicker adapter for that (if no such interface is available,
use the item itself).
3. Find a IActionProvider adapters for the selected (focused) item.
4. Update the popup menu context (actions) for the selected item.

View File

@ -8,17 +8,17 @@
# All configuration values have a default; values that are commented out
# serve to show the default.
import sys, os
from __future__ import absolute_import
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#sys.path.insert(0, os.path.abspath('.'))
# sys.path.insert(0, os.path.abspath('.'))
# -- General configuration -----------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here.
#needs_sphinx = '1.0'
# needs_sphinx = '1.0'
# Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
@ -31,14 +31,14 @@ templates_path = ['_templates']
source_suffix = '.txt'
# The encoding of source files.
#source_encoding = 'utf-8-sig'
# source_encoding = 'utf-8-sig'
# The master toctree document.
master_doc = 'contents'
master_doc = 'index'
# General information about the project.
project = u'Gaphor'
copyright = u'2012, Gaphor development team'
copyright = u'2012 Arjan Molenaar, 2017 Dan Yeaw'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
@ -51,37 +51,37 @@ release = '0.17.1'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#language = None
# language = None
# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
#today = ''
# today = ''
# Else, today_fmt is used as the format for a strftime call.
#today_fmt = '%B %d, %Y'
# today_fmt = '%B %d, %Y'
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
exclude_patterns = ['_build']
# The reST default role (used for this markup: `text`) to use for all documents.
#default_role = None
# default_role = None
# If true, '()' will be appended to :func: etc. cross-reference text.
#add_function_parentheses = True
# add_function_parentheses = True
# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
#add_module_names = True
# add_module_names = True
# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
#show_authors = False
# show_authors = False
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
# A list of ignored prefixes for module index sorting.
#modindex_common_prefix = []
# modindex_common_prefix = []
# -- Options for HTML output ---------------------------------------------------
@ -93,26 +93,26 @@ html_theme = 'default'
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
#html_theme_options = {}
# html_theme_options = {}
# Add any paths that contain custom themes here, relative to this directory.
#html_theme_path = []
# html_theme_path = []
# The name for this set of Sphinx documents. If None, it defaults to
# "<project> v<release> documentation".
#html_title = None
# html_title = None
# A shorter title for the navigation bar. Default is the same as html_title.
#html_short_title = None
# html_short_title = None
# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
#html_logo = None
# html_logo = None
# The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
#html_favicon = None
# html_favicon = None
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
@ -121,86 +121,85 @@ html_static_path = ['_static']
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
#html_last_updated_fmt = '%b %d, %Y'
# html_last_updated_fmt = '%b %d, %Y'
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
#html_use_smartypants = True
# html_use_smartypants = True
# Custom sidebar templates, maps document names to template names.
#html_sidebars = {}
# html_sidebars = {}
# Additional templates that should be rendered to pages, maps page names to
# template names.
#html_additional_pages = {}
# html_additional_pages = {}
# If false, no module index is generated.
#html_domain_indices = True
# html_domain_indices = True
# If false, no index is generated.
#html_use_index = True
# html_use_index = True
# If true, the index is split into individual pages for each letter.
#html_split_index = False
# html_split_index = False
# If true, links to the reST sources are added to the pages.
#html_show_sourcelink = True
# html_show_sourcelink = True
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
#html_show_sphinx = True
# html_show_sphinx = True
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
#html_show_copyright = True
# html_show_copyright = True
# If true, an OpenSearch description file will be output, and all pages will
# contain a <link> tag referring to it. The value of this option must be the
# base URL from which the finished HTML is served.
#html_use_opensearch = ''
# html_use_opensearch = ''
# This is the file name suffix for HTML files (e.g. ".xhtml").
#html_file_suffix = None
# html_file_suffix = None
# Output file base name for HTML help builder.
htmlhelp_basename = 'Gaphordoc'
# -- Options for LaTeX output --------------------------------------------------
# The paper size ('letter' or 'a4').
#latex_paper_size = 'letter'
# latex_paper_size = 'letter'
# The font size ('10pt', '11pt' or '12pt').
#latex_font_size = '10pt'
# latex_font_size = '10pt'
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, documentclass [howto/manual]).
latex_documents = [
('contents', 'Gaphor.tex', u'Gaphor Documentation',
u'Gaphor development team', 'manual'),
('index', 'Gaphor.tex', u'Gaphor Documentation',
u'Dan Yeaw', 'manual'),
]
# The name of an image file (relative to this directory) to place at the top of
# the title page.
#latex_logo = None
# latex_logo = None
# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
#latex_use_parts = False
# latex_use_parts = False
# If true, show page references after internal links.
#latex_show_pagerefs = False
# latex_show_pagerefs = False
# If true, show URL addresses after external links.
#latex_show_urls = False
# latex_show_urls = False
# Additional stuff for the LaTeX preamble.
#latex_preamble = ''
# latex_preamble = ''
# Documents to append as an appendix to all manuals.
#latex_appendices = []
# latex_appendices = []
# If false, no module index is generated.
#latex_domain_indices = True
# latex_domain_indices = True
# -- Options for manual page output --------------------------------------------
@ -208,6 +207,6 @@ latex_documents = [
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
('contents', 'gaphor', u'Gaphor Documentation',
[u'Gaphor development team'], 1)
('index', 'gaphor', u'Gaphor Documentation',
[u'Dan Yeaw and contributors'], 1)
]

View File

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 27 KiB

View File

Before

Width:  |  Height:  |  Size: 4.6 KiB

After

Width:  |  Height:  |  Size: 4.6 KiB

View File

Before

Width:  |  Height:  |  Size: 9.6 KiB

After

Width:  |  Height:  |  Size: 9.6 KiB

View File

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

View File

Before

Width:  |  Height:  |  Size: 8.7 KiB

After

Width:  |  Height:  |  Size: 8.7 KiB

View File

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 32 KiB

View File

@ -1,24 +1,40 @@
#!/usr/bin/python
#!/usr/bin/env python
"""This script list classes and optionally attributes from UML model
created with Gaphor."""
# Copyright (C) 2008-2017 Adam Boduch <adam.boduch@gmail.com>
# Artur Wroblewski <wrobell@pld-linux.org>
# Dan Yeaw <dan@yeaw.me>
#
# This file is part of Gaphor.
#
# Gaphor is free software: you can redistribute it and/or modify it under the
# terms of the GNU Library General Public License as published by the Free
# Software Foundation, either version 2 of the License, or (at your option)
# any later version.
#
# Gaphor is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
# more details.
#
# You should have received a copy of the GNU Library General Public
# along with Gaphor. If not, see <http://www.gnu.org/licenses/>.
"""This script list classes and optionally attributes from UML model created with Gaphor."""
from __future__ import absolute_import
from __future__ import print_function
import sys
import optparse
import sys
from gaphor.UML import uml2
from gaphor import Application
import gaphor.UML as UML
#Setup command line options.
# Setup command line options.
usage = 'usage: %prog [options] file.gaphor'
parser = optparse.OptionParser(usage=usage)
parser.add_option('-a',\
'--attributes',\
dest='attrs',\
action='store_true',\
help='Print class attributes')
parser.add_option('-a', '--attributes', dest='attrs', action='store_true', help='Print class attributes')
(options, args) = parser.parse_args()
@ -26,26 +42,25 @@ if len(args) != 1:
parser.print_help()
sys.exit(1)
#The model file to load.
# The model file to load.
model = args[0]
#Create the Gaphor application object.
# Create the Gaphor application object.
Application.init()
#Get services we need.
# Get services we need.
element_factory = Application.get_service('element_factory')
file_manager = Application.get_service('file_manager')
#Load model from file.
# Load model from file.
file_manager.load(model)
#Find all classes using factory select.
for cls in element_factory.select(lambda e: e.isKindOf(UML.Class)):
print 'Found class %s' % cls.name
# Find all classes using factory select.
for cls in element_factory.select(lambda e: e.isKindOf(uml2.Class)):
print('Found class %s' % cls.name)
if options.attrs:
for attr in cls.ownedAttribute:
print ' Attribute: %s' % attr.name
print(' Attribute: %s' % attr.name)

View File

@ -1,284 +0,0 @@
#!python
"""Bootstrap setuptools installation
If you want to use setuptools in your package's setup.py, just include this
file in the same directory with it, and add this to the top of your setup.py::
from ez_setup import use_setuptools
use_setuptools()
If you want to require a specific version of setuptools, set a download
mirror, or use an alternate download directory, you can do so by supplying
the appropriate options to ``use_setuptools()``.
This file can also be run as a script to install or upgrade setuptools.
"""
import sys
DEFAULT_VERSION = "0.6c11"
DEFAULT_URL = "http://pypi.python.org/packages/%s/s/setuptools/" % sys.version[:3]
md5_data = {
'setuptools-0.6b1-py2.3.egg': '8822caf901250d848b996b7f25c6e6ca',
'setuptools-0.6b1-py2.4.egg': 'b79a8a403e4502fbb85ee3f1941735cb',
'setuptools-0.6b2-py2.3.egg': '5657759d8a6d8fc44070a9d07272d99b',
'setuptools-0.6b2-py2.4.egg': '4996a8d169d2be661fa32a6e52e4f82a',
'setuptools-0.6b3-py2.3.egg': 'bb31c0fc7399a63579975cad9f5a0618',
'setuptools-0.6b3-py2.4.egg': '38a8c6b3d6ecd22247f179f7da669fac',
'setuptools-0.6b4-py2.3.egg': '62045a24ed4e1ebc77fe039aa4e6f7e5',
'setuptools-0.6b4-py2.4.egg': '4cb2a185d228dacffb2d17f103b3b1c4',
'setuptools-0.6c1-py2.3.egg': 'b3f2b5539d65cb7f74ad79127f1a908c',
'setuptools-0.6c1-py2.4.egg': 'b45adeda0667d2d2ffe14009364f2a4b',
'setuptools-0.6c10-py2.3.egg': 'ce1e2ab5d3a0256456d9fc13800a7090',
'setuptools-0.6c10-py2.4.egg': '57d6d9d6e9b80772c59a53a8433a5dd4',
'setuptools-0.6c10-py2.5.egg': 'de46ac8b1c97c895572e5e8596aeb8c7',
'setuptools-0.6c10-py2.6.egg': '58ea40aef06da02ce641495523a0b7f5',
'setuptools-0.6c11-py2.3.egg': '2baeac6e13d414a9d28e7ba5b5a596de',
'setuptools-0.6c11-py2.4.egg': 'bd639f9b0eac4c42497034dec2ec0c2b',
'setuptools-0.6c11-py2.5.egg': '64c94f3bf7a72a13ec83e0b24f2749b2',
'setuptools-0.6c11-py2.6.egg': 'bfa92100bd772d5a213eedd356d64086',
'setuptools-0.6c2-py2.3.egg': 'f0064bf6aa2b7d0f3ba0b43f20817c27',
'setuptools-0.6c2-py2.4.egg': '616192eec35f47e8ea16cd6a122b7277',
'setuptools-0.6c3-py2.3.egg': 'f181fa125dfe85a259c9cd6f1d7b78fa',
'setuptools-0.6c3-py2.4.egg': 'e0ed74682c998bfb73bf803a50e7b71e',
'setuptools-0.6c3-py2.5.egg': 'abef16fdd61955514841c7c6bd98965e',
'setuptools-0.6c4-py2.3.egg': 'b0b9131acab32022bfac7f44c5d7971f',
'setuptools-0.6c4-py2.4.egg': '2a1f9656d4fbf3c97bf946c0a124e6e2',
'setuptools-0.6c4-py2.5.egg': '8f5a052e32cdb9c72bcf4b5526f28afc',
'setuptools-0.6c5-py2.3.egg': 'ee9fd80965da04f2f3e6b3576e9d8167',
'setuptools-0.6c5-py2.4.egg': 'afe2adf1c01701ee841761f5bcd8aa64',
'setuptools-0.6c5-py2.5.egg': 'a8d3f61494ccaa8714dfed37bccd3d5d',
'setuptools-0.6c6-py2.3.egg': '35686b78116a668847237b69d549ec20',
'setuptools-0.6c6-py2.4.egg': '3c56af57be3225019260a644430065ab',
'setuptools-0.6c6-py2.5.egg': 'b2f8a7520709a5b34f80946de5f02f53',
'setuptools-0.6c7-py2.3.egg': '209fdf9adc3a615e5115b725658e13e2',
'setuptools-0.6c7-py2.4.egg': '5a8f954807d46a0fb67cf1f26c55a82e',
'setuptools-0.6c7-py2.5.egg': '45d2ad28f9750e7434111fde831e8372',
'setuptools-0.6c8-py2.3.egg': '50759d29b349db8cfd807ba8303f1902',
'setuptools-0.6c8-py2.4.egg': 'cba38d74f7d483c06e9daa6070cce6de',
'setuptools-0.6c8-py2.5.egg': '1721747ee329dc150590a58b3e1ac95b',
'setuptools-0.6c9-py2.3.egg': 'a83c4020414807b496e4cfbe08507c03',
'setuptools-0.6c9-py2.4.egg': '260a2be2e5388d66bdaee06abec6342a',
'setuptools-0.6c9-py2.5.egg': 'fe67c3e5a17b12c0e7c541b7ea43a8e6',
'setuptools-0.6c9-py2.6.egg': 'ca37b1ff16fa2ede6e19383e7b59245a',
}
import sys, os
try: from hashlib import md5
except ImportError: from md5 import md5
def _validate_md5(egg_name, data):
if egg_name in md5_data:
digest = md5(data).hexdigest()
if digest != md5_data[egg_name]:
print >>sys.stderr, (
"md5 validation of %s failed! (Possible download problem?)"
% egg_name
)
sys.exit(2)
return data
def use_setuptools(
version=DEFAULT_VERSION, download_base=DEFAULT_URL, to_dir=os.curdir,
download_delay=15
):
"""Automatically find/download setuptools and make it available on sys.path
`version` should be a valid setuptools version number that is available
as an egg for download under the `download_base` URL (which should end with
a '/'). `to_dir` is the directory where setuptools will be downloaded, if
it is not already available. If `download_delay` is specified, it should
be the number of seconds that will be paused before initiating a download,
should one be required. If an older version of setuptools is installed,
this routine will print a message to ``sys.stderr`` and raise SystemExit in
an attempt to abort the calling script.
"""
was_imported = 'pkg_resources' in sys.modules or 'setuptools' in sys.modules
def do_download():
egg = download_setuptools(version, download_base, to_dir, download_delay)
sys.path.insert(0, egg)
import setuptools; setuptools.bootstrap_install_from = egg
try:
import pkg_resources
except ImportError:
return do_download()
try:
pkg_resources.require("setuptools>="+version); return
except pkg_resources.VersionConflict, e:
if was_imported:
print >>sys.stderr, (
"The required version of setuptools (>=%s) is not available, and\n"
"can't be installed while this script is running. Please install\n"
" a more recent version first, using 'easy_install -U setuptools'."
"\n\n(Currently using %r)"
) % (version, e.args[0])
sys.exit(2)
else:
del pkg_resources, sys.modules['pkg_resources'] # reload ok
return do_download()
except pkg_resources.DistributionNotFound:
return do_download()
def download_setuptools(
version=DEFAULT_VERSION, download_base=DEFAULT_URL, to_dir=os.curdir,
delay = 15
):
"""Download setuptools from a specified location and return its filename
`version` should be a valid setuptools version number that is available
as an egg for download under the `download_base` URL (which should end
with a '/'). `to_dir` is the directory where the egg will be downloaded.
`delay` is the number of seconds to pause before an actual download attempt.
"""
import urllib2, shutil
egg_name = "setuptools-%s-py%s.egg" % (version,sys.version[:3])
url = download_base + egg_name
saveto = os.path.join(to_dir, egg_name)
src = dst = None
if not os.path.exists(saveto): # Avoid repeated downloads
try:
from distutils import log
if delay:
log.warn("""
---------------------------------------------------------------------------
This script requires setuptools version %s to run (even to display
help). I will attempt to download it for you (from
%s), but
you may need to enable firewall access for this script first.
I will start the download in %d seconds.
(Note: if this machine does not have network access, please obtain the file
%s
and place it in this directory before rerunning this script.)
---------------------------------------------------------------------------""",
version, download_base, delay, url
); from time import sleep; sleep(delay)
log.warn("Downloading %s", url)
src = urllib2.urlopen(url)
# Read/write all in one block, so we don't create a corrupt file
# if the download is interrupted.
data = _validate_md5(egg_name, src.read())
dst = open(saveto,"wb"); dst.write(data)
finally:
if src: src.close()
if dst: dst.close()
return os.path.realpath(saveto)
def main(argv, version=DEFAULT_VERSION):
"""Install or upgrade setuptools and EasyInstall"""
try:
import setuptools
except ImportError:
egg = None
try:
egg = download_setuptools(version, delay=0)
sys.path.insert(0,egg)
from setuptools.command.easy_install import main
return main(list(argv)+[egg]) # we're done here
finally:
if egg and os.path.exists(egg):
os.unlink(egg)
else:
if setuptools.__version__ == '0.0.1':
print >>sys.stderr, (
"You have an obsolete version of setuptools installed. Please\n"
"remove it from your system entirely before rerunning this script."
)
sys.exit(2)
req = "setuptools>="+version
import pkg_resources
try:
pkg_resources.require(req)
except pkg_resources.VersionConflict:
try:
from setuptools.command.easy_install import main
except ImportError:
from easy_install import main
main(list(argv)+[download_setuptools(delay=0)])
sys.exit(0) # try to force an exit
else:
if argv:
from setuptools.command.easy_install import main
main(argv)
else:
print "Setuptools version",version,"or greater has been installed."
print '(Run "ez_setup.py -U setuptools" to reinstall or upgrade.)'
def update_md5(filenames):
"""Update our built-in md5 registry"""
import re
for name in filenames:
base = os.path.basename(name)
f = open(name,'rb')
md5_data[base] = md5(f.read()).hexdigest()
f.close()
data = [" %r: %r,\n" % it for it in md5_data.items()]
data.sort()
repl = "".join(data)
import inspect
srcfile = inspect.getsourcefile(sys.modules[__name__])
f = open(srcfile, 'rb'); src = f.read(); f.close()
match = re.search("\nmd5_data = {\n([^}]+)}", src)
if not match:
print >>sys.stderr, "Internal error!"
sys.exit(2)
src = src[:match.start(1)] + repl + src[match.end(1):]
f = open(srcfile,'w')
f.write(src)
f.close()
if __name__=='__main__':
if len(sys.argv)>2 and sys.argv[1]=='--md5update':
update_md5(sys.argv[2:])
else:
main(sys.argv[1:])

View File

@ -1,7 +1,33 @@
from gaphor.UML.collection import collection
#!/usr/bin/env python
from gaphor.UML.uml2 import *
from gaphor.UML.elementfactory import ElementFactory
from gaphor.UML import modelfactory as model
from gaphor.UML.umlfmt import format
from gaphor.UML.umllex import parse
# Copyright (C) 2001-2017 Arjan Molenaar <gaphor@gmail.com>
# Artur Wroblewski <wrobell@pld-linux.org>
# Dan Yeaw <dan@yeaw.me>
# syt <noreply@example.com>
#
# This file is part of Gaphor.
#
# Gaphor is free software: you can redistribute it and/or modify it under the
# terms of the GNU Library General Public License as published by the Free
# Software Foundation, either version 2 of the License, or (at your option)
# any later version.
#
# Gaphor is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
# more details.
#
# You should have received a copy of the GNU Library General Public
# along with Gaphor. If not, see <http://www.gnu.org/licenses/>.
from __future__ import absolute_import
#from gaphor.UML.collection import collection
#from gaphor.UML.uml2 import Diagram
#from gaphor.UML.elementfactory import ElementFactory
#from gaphor.UML import modelfactory as model
#from gaphor.UML.umlfmt import format
#from gaphor.UML.umllex import parse
__all__ = ['collection', 'context', 'diagram', 'element', 'elementfactory', 'event', 'interface', 'modelfactory',
'properties', 'uml2', 'umlfmt', 'umllex']

View File

@ -1,10 +1,33 @@
#!/usr/bin/env python
# Copyright (C) 2002-2017 Arjan Molenaar <gaphor@gmail.com>
# Artur Wroblewski <wrobell@pld-linux.org>
# Dan Yeaw <dan@yeaw.me>
#
# This file is part of Gaphor.
#
# Gaphor is free software: you can redistribute it and/or modify it under the
# terms of the GNU Library General Public License as published by the Free
# Software Foundation, either version 2 of the License, or (at your option)
# any later version.
#
# Gaphor is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
# more details.
#
# You should have received a copy of the GNU Library General Public
# along with Gaphor. If not, see <http://www.gnu.org/licenses/>.
"""
1:n and n:m relations in the data model are saved using a collection.
"""
from __future__ import absolute_import
import inspect
from event import AssociationChangeEvent
from gaphor.misc.listmixins import querymixin, recursemixin, recurseproxy, getslicefix
from gaphor.UML.event import AssociationChangeEvent
from gaphor.misc.listmixins import querymixin, recursemixin, getslicefix
class collectionlist(recursemixin, querymixin, getslicefix, list):
@ -18,16 +41,16 @@ class collectionlist(recursemixin, querymixin, getslicefix, list):
It should work with the datamodel too:
>>> from gaphor.UML import *
>>> c = Class()
>>> c.ownedOperation = Operation()
>>> from gaphor.UML import uml2
>>> c = uml2.Class()
>>> c.ownedOperation = uml2.Operation()
>>> c.ownedOperation # doctest: +ELLIPSIS
[<gaphor.UML.uml2.Operation object at 0x...>]
>>> c.ownedOperation[0] # doctest: +ELLIPSIS
<gaphor.UML.uml2.Operation object at 0x...>
>>> c.ownedOperation = Operation()
>>> c.ownedOperation[0].formalParameter = Parameter()
>>> c.ownedOperation[0].formalParameter = Parameter()
>>> c.ownedOperation = uml2.Operation()
>>> c.ownedOperation[0].formalParameter = uml2.Parameter()
>>> c.ownedOperation[0].formalParameter = uml2.Parameter()
>>> c.ownedOperation[0].formalParameter[0].name = 'foo'
>>> c.ownedOperation[0].formalParameter[0].name
'foo'
@ -60,7 +83,7 @@ class collection(object):
return len(self.items)
def __setitem__(self, key, value):
raise RuntimeError, 'items should not be overwritten.'
raise RuntimeError('items should not be overwritten.')
def __delitem__(self, key):
self.remove(key)
@ -80,20 +103,19 @@ class collection(object):
__repr__ = __str__
def __nonzero__(self):
return self.items!=[]
return self.items != []
def append(self, value):
if isinstance(value, self.type):
self.property._set(self.object, value)
else:
raise TypeError, 'Object is not of type %s' % self.type.__name__
raise TypeError('Object is not of type %s' % self.type.__name__)
def remove(self, value):
if value in self.items:
self.property.__delete__(self.object, value)
else:
raise ValueError, '%s not in collection' % value
raise ValueError('%s not in collection' % value)
def index(self, key):
"""
@ -102,131 +124,129 @@ class collection(object):
"""
return self.items.index(key)
# OCL members (from SMW by Ivan Porres, http://www.abo.fi/~iporres/smw)
def size(self):
return len(self.items)
def includes(self,o):
def includes(self, o):
return o in self.items
def excludes(self,o):
def excludes(self, o):
return not self.includes(o)
def count(self,o):
c=0
def count(self, o):
c = 0
for x in self.items:
if x==o:
c=c+1
if x == o:
c += 1
return c
def includesAll(self,c):
def includesAll(self, c):
for o in c:
if o not in self.items:
return 0
return 1
def excludesAll(self,c):
def excludesAll(self, c):
for o in c:
if o in self.items:
return 0
return 1
def select(self,f):
result=list()
def select(self, f):
result = list()
for v in self.items:
if f(v):
result.append(v)
return result
def reject(self,f):
result=list()
def reject(self, f):
result = list()
for v in self.items:
if not f(v):
result.append(v)
return result
def collect(self,f):
result=list()
def collect(self, f):
result = list()
for v in self.items:
result.append(f(v))
return result
def isEmpty(self):
return len(self.items)==0
return len(self.items) == 0
def nonEmpty(self):
return not self.isEmpty()
def sum(self):
r=0
r = 0
for o in self.items:
r=r+o
r = r + o
return o
def forAll(self,f):
def forAll(self, f):
if not self.items or not inspect.getargspec(f)[0]:
return True
nargs=len(inspect.getargspec(f)[0])
nargs = len(inspect.getargspec(f)[0])
if inspect.getargspec(f)[3]:
nargs=nargs-len(inspect.getargspec(f)[3])
assert(nargs>0)
nitems=len(self.items)
index=[0]*nargs
nargs -= len(inspect.getargspec(f)[3])
assert (nargs > 0)
nitems = len(self.items)
index = [0] * nargs
while 1:
args=[]
args = []
for x in index:
args.append(self.items[x])
if not apply(f,args):
if not f(*args):
return False
c=len(index)-1
index[c]=index[c]+1
while index[c]==nitems:
index[c]=0
c=c-1
if c<0:
c = len(index) - 1
index[c] += 1
while index[c] == nitems:
index[c] = 0
c = c - 1
if c < 0:
return True
else:
index[c]=index[c]+1
if index[c]==nitems-1:
c=c-1
index[c] += 1
if index[c] == nitems - 1:
c -= 1
return False
def exist(self,f):
def exist(self, f):
if not self.items or not inspect.getargspec(f)[0]:
return False
nargs=len(inspect.getargspec(f)[0])
nargs = len(inspect.getargspec(f)[0])
if inspect.getargspec(f)[3]:
nargs=nargs-len(inspect.getargspec(f)[3])
assert(nargs>0)
nitems=len(self.items)
index=[0]*nargs
nargs -= len(inspect.getargspec(f)[3])
assert (nargs > 0)
nitems = len(self.items)
index = [0] * nargs
while 1:
args=[]
args = []
for x in index:
args.append(self.items[x])
if apply(f,args):
if f(*args):
return True
c=len(index)-1
index[c]=index[c]+1
while index[c]==nitems:
index[c]=0
c=c-1
if c<0:
c = len(index) - 1
index[c] += 1
while index[c] == nitems:
index[c] = 0
c -= 1
if c < 0:
return False
else:
index[c]=index[c]+1
if index[c]==nitems-1:
c=c-1
index[c] += 1
if index[c] == nitems - 1:
c -= 1
return False
def swap(self, item1, item2):
"""
Swap two elements. Return true if swap was successful.
@ -241,10 +261,9 @@ class collection(object):
if factory:
factory._handle(AssociationChangeEvent(self.object, self.property))
return True
except IndexError, ex:
except IndexError as ex:
return False
except ValueError, ex:
except ValueError as ex:
return False
# vi:sw=4:et:ai

View File

@ -1,12 +1,39 @@
# vim: sw=4
#!/usr/bin/env python
# Copyright (C) 2002-2017 Adam Boduch <adam.boduch@gmail.com>
# Arjan Molenaar <gaphor@gmail.com>
# Artur Wroblewski <wrobell@pld-linux.org>
# Dan Yeaw <dan@yeaw.me>
# syt <noreply@example.com>
#
# This file is part of Gaphor.
#
# Gaphor is free software: you can redistribute it and/or modify it under the
# terms of the GNU Library General Public License as published by the Free
# Software Foundation, either version 2 of the License, or (at your option)
# any later version.
#
# Gaphor is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
# more details.
#
# You should have received a copy of the GNU Library General Public
# along with Gaphor. If not, see <http://www.gnu.org/licenses/>.
"""This module contains a model element Diagram which is the abstract
representation of a UML diagram. Diagrams can be visualized and edited.
The DiagramCanvas class extends the gaphas.Canvas class."""
import gaphas
from __future__ import absolute_import
import uuid
from uml2 import Namespace, PackageableElement
import gaphas
from six.moves import filter
from gaphor.UML.uml2 import Namespace, PackageableElement
class DiagramCanvas(gaphas.Canvas):
"""DiagramCanvas extends the gaphas.Canvas class. Updates to the canvas
@ -17,7 +44,7 @@ class DiagramCanvas(gaphas.Canvas):
def __init__(self, diagram):
"""Initialize the diagram canvas with the supplied diagram. By default,
updates are not blocked."""
super(DiagramCanvas, self).__init__()
self._diagram = diagram
self._block_updates = False
@ -27,7 +54,7 @@ class DiagramCanvas(gaphas.Canvas):
def _set_block_updates(self, block):
"""Sets the block_updates property. If false, the diagram canvas is
updated immediately."""
self._block_updates = block
if not block:
self.update_now()
@ -36,14 +63,14 @@ class DiagramCanvas(gaphas.Canvas):
def update_now(self):
"""Update the diagram canvas, unless block_updates is true."""
if self._block_updates:
return
super(DiagramCanvas, self).update_now()
def save(self, save_func):
"""Apply the supplied save function to all root diagram items."""
for item in self.get_root_items():
save_func(None, item)
@ -54,8 +81,8 @@ class DiagramCanvas(gaphas.Canvas):
def select(self, expression=lambda e: True):
"""Return a list of all canvas items that match expression."""
return filter(expression, self.get_all_items())
return list(filter(expression, self.get_all_items()))
class Diagram(Namespace, PackageableElement):
@ -65,13 +92,13 @@ class Diagram(Namespace, PackageableElement):
def __init__(self, id=None, factory=None):
"""Initialize the diagram with an optional id and element factory.
The diagram also has a canvas."""
super(Diagram, self).__init__(id, factory)
self.canvas = DiagramCanvas(self)
def save(self, save_func):
"""Apply the supplied save function to this diagram and the canvas."""
super(Diagram, self).save(save_func)
save_func('canvas', self.canvas)
@ -85,7 +112,7 @@ class Diagram(Namespace, PackageableElement):
a unique ID and it is attached to the diagram's root item. The type
parameter is the element class to create. The new element also has an
optional parent and subject."""
assert issubclass(type, gaphas.Item)
obj = type(str(uuid.uuid1()))
if subject:
@ -95,7 +122,7 @@ class Diagram(Namespace, PackageableElement):
def unlink(self):
"""Unlink all canvas items then unlink this diagram."""
for item in self.canvas.get_all_items():
try:
item.unlink()

View File

@ -1,13 +1,36 @@
#!/usr/bin/env python
# Copyright (C) 2001-2017 Adam Boduch <adam.boduch@gmail.com>
# Arjan Molenaar <gaphor@gmail.com>
# Dan Yeaw <dan@yeaw.me>
# syt <noreply@example.com>
#
# This file is part of Gaphor.
#
# Gaphor is free software: you can redistribute it and/or modify it under the
# terms of the GNU Library General Public License as published by the Free
# Software Foundation, either version 2 of the License, or (at your option)
# any later version.
#
# Gaphor is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
# more details.
#
# You should have received a copy of the GNU Library General Public
# along with Gaphor. If not, see <http://www.gnu.org/licenses/>.
"""
Base class for UML model elements.
"""
__all__ = [ 'Element' ]
from __future__ import absolute_import
import threading
import uuid
from properties import umlproperty
from .properties import umlproperty
__all__ = ['Element']
class Element(object):
@ -33,14 +56,11 @@ class Element(object):
self._factory = factory
self._unlink_lock = threading.Lock()
id = property(lambda self: self._id, doc='Id')
factory = property(lambda self: self._factory,
doc="The factory that created this element")
def umlproperties(self):
"""
Iterate over all UML properties
@ -53,7 +73,6 @@ class Element(object):
if isinstance(prop, umlprop):
yield prop
def save(self, save_func):
"""
Save the state by calling save_func(name, value).
@ -61,7 +80,6 @@ class Element(object):
for prop in self.umlproperties():
prop.save(self, save_func)
def load(self, name, value):
"""
Loads value in name. Make sure that for every load postload()
@ -69,13 +87,11 @@ class Element(object):
"""
try:
prop = getattr(type(self), name)
except AttributeError, e:
raise AttributeError, "'%s' has no property '%s'" % \
(type(self).__name__, name)
except AttributeError as e:
raise AttributeError("'%s' has no property '%s'" % (type(self).__name__, name))
else:
prop.load(self, value)
def postload(self):
"""
Fix up the odds and ends.
@ -83,26 +99,22 @@ class Element(object):
for prop in self.umlproperties():
prop.postload(self)
def unlink(self):
"""Unlink the element. All the elements references are destroyed.
The unlink lock is acquired while unlinking this elements properties
to avoid recursion problems."""
if self._unlink_lock.locked():
return
with self._unlink_lock:
for prop in self.umlproperties():
prop.unlink(self)
if self._factory:
self._factory._unlink_element(self)
# OCL methods: (from SMW by Ivan Porres (http://www.abo.fi/~iporres/smw))
@ -113,14 +125,12 @@ class Element(object):
"""
return isinstance(self, class_)
def isTypeOf(self, other):
"""
Returns true if the object is of the same type as other.
"""
return type(self) == type(other)
def __getstate__(self):
d = dict(self.__dict__)
try:
@ -129,7 +139,6 @@ class Element(object):
pass
return d
def __setstate__(self, state):
self._factory = None
self.__dict__.update(state)

View File

@ -1,21 +1,44 @@
# vim: sw=4
#!/usr/bin/env python
# Copyright (C) 2002-2017 Adam Boduch <adam.boduch@gmail.com>
# Arjan Molenaar <gaphor@gmail.com>
# Artur Wroblewski <wrobell@pld-linux.org>
# Dan Yeaw <dan@yeaw.me>
# syt <noreply@example.com>
#
# This file is part of Gaphor.
#
# Gaphor is free software: you can redistribute it and/or modify it under the
# terms of the GNU Library General Public License as published by the Free
# Software Foundation, either version 2 of the License, or (at your option)
# any later version.
#
# Gaphor is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
# more details.
#
# You should have received a copy of the GNU Library General Public
# along with Gaphor. If not, see <http://www.gnu.org/licenses/>.
"""
Factory for and registration of model elements.
"""
from zope import interface
from zope import component
from __future__ import absolute_import
import uuid
from gaphor.core import inject
from gaphor.misc import odict
from gaphor.interfaces import IService, IEventFilter
from gaphor.UML.interfaces import IElementCreateEvent, IElementDeleteEvent, \
IFlushFactoryEvent, IModelFactoryEvent, \
IElementChangeEvent, IElementEvent
from gaphor.UML.event import ElementCreateEvent, ElementDeleteEvent, \
FlushFactoryEvent, ModelFactoryEvent
from zope import component
from zope import interface
import six
from gaphor.UML.element import Element
from gaphor.UML.diagram import Diagram
from gaphor.UML.event import ElementCreateEvent, ElementDeleteEvent, FlushFactoryEvent, ModelFactoryEvent
from gaphor.UML.interfaces import IElementChangeEvent
from gaphor.UML.uml2 import Diagram
from gaphor.core import inject
from gaphor.interfaces import IService, IEventFilter
from gaphor.misc import odict
class ElementFactory(object):
@ -31,6 +54,7 @@ class ElementFactory(object):
flush - model is flushed: all element are removed from the factory
(element is None)
"""
def __init__(self):
self._elements = odict.odict()
self._observers = list()
@ -59,13 +83,12 @@ class ElementFactory(object):
The element may not be bound to another factory already.
"""
if hasattr(element, '_factory') and element._factory:
raise AttributeError, "element is already bound"
raise AttributeError("element is already bound")
if self._elements.get(element.id):
raise AttributeError, "an element already exists with the same id"
raise AttributeError("an element already exists with the same id")
element._factory = self
self._elements[element.id] = element
def size(self):
"""
@ -73,68 +96,58 @@ class ElementFactory(object):
"""
return len(self._elements)
def lookup(self, id):
"""
Find element with a specific id.
"""
return self._elements.get(id)
__getitem__ = lookup
def __contains__(self, element):
return self.lookup(element.id) is element
def select(self, expression=None):
"""
Iterate elements that comply with expression.
"""
if expression is None:
for e in self._elements.itervalues():
for e in six.itervalues(self._elements):
yield e
else:
for e in self._elements.itervalues():
for e in six.itervalues(self._elements):
if expression(e):
yield e
def lselect(self, expression=None):
"""
Like select(), but returns a list.
"""
return list(self.select(expression))
def keys(self):
"""
Return a list with all id's in the factory.
"""
return self._elements.keys()
return list(self._elements.keys())
def iterkeys(self):
"""
Return a iterator with all id's in the factory.
"""
return self._elements.iterkeys()
return six.iterkeys(self._elements)
def values(self):
"""
Return a list with all elements in the factory.
"""
return self._elements.values()
return list(self._elements.values())
def itervalues(self):
"""
Return a iterator with all elements in the factory.
"""
return self._elements.itervalues()
return six.itervalues(self._elements)
def is_empty(self):
"""
@ -142,19 +155,18 @@ class ElementFactory(object):
"""
return bool(self._elements)
def flush(self):
"""Flush all elements (remove them from the factory).
Diagram elements are flushed first. This is so that canvas updates
are blocked. The remaining elements are then flushed.
"""
flush_element = self._flush_element
for element in self.lselect(lambda e: isinstance(e, Diagram)):
element.canvas.block_updates = True
flush_element(element)
for element in self.lselect():
flush_element(element)
@ -171,7 +183,7 @@ class ElementFactory(object):
pass
def swap_element(self, element, new_class):
assert element in self._elements.values()
assert element in list(self._elements.values())
if element.__class__ is not new_class:
element.__class__ = new_class
@ -215,7 +227,7 @@ class ElementFactoryService(ElementFactory):
are blocked. The remaining elements are then flushed. Finally,
the ElementChangedEventBlocker adapter is unregistered if the factory
has an application instance."""
self.component_registry.handle(FlushFactoryEvent(self))
self.component_registry.register_subscription_adapter(ElementChangedEventBlocker)
@ -263,6 +275,4 @@ class ElementChangedEventBlocker(object):
"""
return 'Blocked by ElementFactory.flush()'
# vim:sw=4:et

View File

@ -1,6 +1,27 @@
#!/usr/bin/env python
# Copyright (C) 2007-2017 Adam Boduch <adam.boduch@gmail.com>
# Arjan Molenaar <gaphor@gmail.com>
# Dan Yeaw <dan@yeaw.me>
#
# This file is part of Gaphor.
#
# Gaphor is free software: you can redistribute it and/or modify it under the
# terms of the GNU Library General Public License as published by the Free
# Software Foundation, either version 2 of the License, or (at your option)
# any later version.
#
# Gaphor is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
# more details.
#
# You should have received a copy of the GNU Library General Public
# along with Gaphor. If not, see <http://www.gnu.org/licenses/>.
"""The core UML metamodel events."""
from interfaces import *
from __future__ import absolute_import
from .interfaces import *
from zope import interface
class AttributeChangeEvent(object):

View File

@ -1,7 +1,27 @@
#!/usr/bin/env python
# Copyright (C) 2007-2017 Arjan Molenaar <gaphor@gmail.com>
# Dan Yeaw <dan@yeaw.me>
#
# This file is part of Gaphor.
#
# Gaphor is free software: you can redistribute it and/or modify it under the
# terms of the GNU Library General Public License as published by the Free
# Software Foundation, either version 2 of the License, or (at your option)
# any later version.
#
# Gaphor is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
# more details.
#
# You should have received a copy of the GNU Library General Public
# along with Gaphor. If not, see <http://www.gnu.org/licenses/>.
"""
UML events emited on a change in the data model.
"""
from __future__ import absolute_import
from zope import interface
from gaphor.interfaces import IServiceEvent

View File

@ -1,3 +1,23 @@
#!/usr/bin/env python
# Copyright (C) 2009-2017 Arjan Molenaar <gaphor@gmail.com>
# Artur Wroblewski <wrobell@pld-linux.org>
# Dan Yeaw <dan@yeaw.me>
#
# This file is part of Gaphor.
#
# Gaphor is free software: you can redistribute it and/or modify it under the
# terms of the GNU Library General Public License as published by the Free
# Software Foundation, either version 2 of the License, or (at your option)
# any later version.
#
# Gaphor is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
# more details.
#
# You should have received a copy of the GNU Library General Public
# along with Gaphor. If not, see <http://www.gnu.org/licenses/>.
"""
UML model support functions.
@ -8,7 +28,7 @@ Functions collected in this module allow to
"""
import itertools
from __future__ import absolute_import
from gaphor.UML.uml2 import *
# '<<%s>>'

View File

@ -1,3 +1,24 @@
#!/usr/bin/env python
# Copyright (C) 2003-2017 Adam Boduch <adam.boduch@gmail.com>
# Arjan Molenaar <gaphor@gmail.com>
# Artur Wroblewski <wrobell@pld-linux.org>
# Dan Yeaw <dan@yeaw.me>
#
# This file is part of Gaphor.
#
# Gaphor is free software: you can redistribute it and/or modify it under the
# terms of the GNU Library General Public License as published by the Free
# Software Foundation, either version 2 of the License, or (at your option)
# any later version.
#
# Gaphor is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
# more details.
#
# You should have received a copy of the GNU Library General Public
# along with Gaphor. If not, see <http://www.gnu.org/licenses/>.
"""
Properties used to create the UML 2.0 data model.
@ -24,16 +45,18 @@ methods:
save(save_func): send the value of the property to save_func(name, value)
"""
from __future__ import absolute_import
from six.moves import map
__all__ = [ 'attribute', 'enumeration', 'association', 'derivedunion', 'redefine' ]
from zope import component
from collection import collection, collectionlist
from event import AttributeChangeEvent, AssociationSetEvent, \
from .collection import collection, collectionlist
from .event import AttributeChangeEvent, AssociationSetEvent, \
AssociationAddEvent, AssociationDeleteEvent
from event import DerivedChangeEvent, DerivedSetEvent, \
from .event import DerivedChangeEvent, DerivedSetEvent, \
DerivedAddEvent, DerivedDeleteEvent
from event import RedefineSetEvent, RedefineAddEvent, RedefineDeleteEvent
from interfaces import IElementChangeEvent, \
from .event import RedefineSetEvent, RedefineAddEvent, RedefineDeleteEvent
from .interfaces import IElementChangeEvent, \
IAssociationChangeEvent, IAssociationSetEvent, \
IAssociationAddEvent, IAssociationDeleteEvent
@ -129,7 +152,7 @@ class attribute(umlproperty):
def _set(self, obj, value):
if value is not None and not isinstance(value, self.type):
raise AttributeError, 'Value should be of type %s' % hasattr(self.type, '__name__') and self.type.__name__ or self.type
raise AttributeError('Value should be of type %s' % hasattr(self.type, '__name__') and self.type.__name__ or self.type)
if value == self._get(obj):
return
@ -186,12 +209,12 @@ class enumeration(umlproperty):
def load(self, obj, value):
if not value in self.values:
raise AttributeError, 'Value should be one of %s' % str(self.values)
raise AttributeError('Value should be one of %s' % str(self.values))
setattr(obj, self._name, value)
def _set(self, obj, value):
if not value in self.values:
raise AttributeError, 'Value should be one of %s' % str(self.values)
raise AttributeError('Value should be one of %s' % str(self.values))
old = self._get(obj)
if value == old:
return
@ -238,7 +261,7 @@ class association(umlproperty):
def load(self, obj, value):
if not isinstance(value, self.type):
raise AttributeError, 'Value for %s should be of type %s (%s)' % (self.name, self.type.__name__, type(value).__name__)
raise AttributeError('Value for %s should be of type %s (%s)' % (self.name, self.type.__name__, type(value).__name__))
self._set(obj, value, do_notify=False)
def postload(self, obj):
@ -253,7 +276,7 @@ class association(umlproperty):
values = [ values ]
for value in values:
if not isinstance(value, self.type):
raise AttributeError, 'Error in postload validation for %s: Value %s should be of type %s' % (self.name, value, self.type.__name__)
raise AttributeError('Error in postload validation for %s: Value %s should be of type %s' % (self.name, value, self.type.__name__))
def __str__(self):
if self.lower == self.upper:
@ -289,7 +312,7 @@ class association(umlproperty):
#print '__set__', self, obj, value, self._get(obj)
if not (isinstance(value, self.type) or \
(value is None and self.upper == 1)):
raise AttributeError, 'Value should be of type %s' % self.type.__name__
raise AttributeError('Value should be of type %s' % self.type.__name__)
# Remove old value only for uni-directional associations
if self.upper == 1:
old = self._get(obj)
@ -348,7 +371,7 @@ class association(umlproperty):
if not value:
if self.upper > 1:
raise Exception, 'Can not delete collections'
raise Exception('Can not delete collections')
old = value = self._get(obj)
if value is None:
return
@ -419,14 +442,14 @@ class associationstub(umlproperty):
def __get__(self, obj, class_=None):
if obj:
raise AssociationStubError, 'getting values not allowed'
raise AssociationStubError('getting values not allowed')
return self
def __set__(self, obj, value):
raise AssociationStubError, 'setting values not allowed'
raise AssociationStubError('setting values not allowed')
def __delete__(self, obj, value=None):
raise AssociationStubError, 'deleting values not allowed'
raise AssociationStubError('deleting values not allowed')
def save(self, obj, save_func):
pass
@ -493,7 +516,7 @@ class derived(umlproperty):
def load(self, obj, value):
raise ValueError, 'Derivedunion: Properties should not be loaded in a derived union %s: %s' % (self.name, value)
raise ValueError('Derivedunion: Properties should not be loaded in a derived union %s: %s' % (self.name, value))
def postload(self, obj):
@ -504,13 +527,13 @@ class derived(umlproperty):
def __str__(self):
return '<derived %s: %s>' % (self.name, str(map(str, self.subsets))[1:-1])
return '<derived %s: %s>' % (self.name, str(list(map(str, self.subsets)))[1:-1])
def filter(self, obj):
"""
Filter should return something iterable.
"""
raise NotImplementedError, 'Implement this in the property.'
raise NotImplementedError('Implement this in the property.')
def _update(self, obj):
"""
@ -523,7 +546,7 @@ class derived(umlproperty):
#if len(u) > 1:
# log.warning('Derived union %s of item %s should have length 1 %s' % (self.name, obj.id, tuple(u)))
if u:
u = iter(u).next()
u = next(iter(u))
else:
u = None
@ -544,11 +567,11 @@ class derived(umlproperty):
def _set(self, obj, value):
raise AttributeError, 'Can not set values on a union'
raise AttributeError('Can not set values on a union')
def _del(self, obj, value=None):
raise AttributeError, 'Can not delete values on a union'
raise AttributeError('Can not delete values on a union')
@component.adapter(IElementChangeEvent)
def _association_changed(self, event):
@ -669,7 +692,7 @@ class derivedunion(derived):
# In an in-between state. Do not emit notifications
return
if values:
new_value = iter(values).next()
new_value = next(iter(values))
self.handle(DerivedSetEvent(event.element, self, old_value, new_value))
else:
if IAssociationSetEvent.providedBy(event):
@ -752,7 +775,7 @@ class redefine(umlproperty):
def __set__(self, obj, value):
# No longer needed
if not isinstance(value, self.type):
raise AttributeError, 'Value should be of type %s' % self.type.__name__
raise AttributeError('Value should be of type %s' % self.type.__name__)
self.original.__set__(obj, value)

View File

@ -1 +1,18 @@
# unit tests
#!/usr/bin/env python
# Copyright (C) 2007 Arjan Molenaar <gaphor@gmail.com>
#
# This file is part of Gaphor.
#
# Gaphor is free software: you can redistribute it and/or modify it under the
# terms of the GNU Library General Public License as published by the Free
# Software Foundation, either version 2 of the License, or (at your option)
# any later version.
#
# Gaphor is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
# more details.
#
# You should have received a copy of the GNU Library General Public
# along with Gaphor. If not, see <http://www.gnu.org/licenses/>.

View File

@ -1,7 +1,27 @@
#!/usr/bin/env python
# Copyright (C) 2009-2017 Arjan Molenaar <gaphor@gmail.com>
# Dan Yeaw <dan@yeaw.me>
#
# This file is part of Gaphor.
#
# Gaphor is free software: you can redistribute it and/or modify it under the
# terms of the GNU Library General Public License as published by the Free
# Software Foundation, either version 2 of the License, or (at your option)
# any later version.
#
# Gaphor is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
# more details.
#
# You should have received a copy of the GNU Library General Public
# along with Gaphor. If not, see <http://www.gnu.org/licenses/>.
"""
Test if the collection's list supports all trickery.
"""
from __future__ import absolute_import
import unittest
from gaphor.UML.collection import collectionlist

View File

@ -1,15 +1,34 @@
#!/usr/bin/env python
# Copyright (C) 2007-2017 Arjan Molenaar <gaphor@gmail.com>
# Dan Yeaw <dan@yeaw.me>
#
# This file is part of Gaphor.
#
# Gaphor is free software: you can redistribute it and/or modify it under the
# terms of the GNU Library General Public License as published by the Free
# Software Foundation, either version 2 of the License, or (at your option)
# any later version.
#
# Gaphor is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
# more details.
#
# You should have received a copy of the GNU Library General Public
# along with Gaphor. If not, see <http://www.gnu.org/licenses/>.
from __future__ import absolute_import
import unittest
from gaphor.UML import *
from gaphor.UML.interfaces import *
from gaphor.UML import interfaces
from gaphor.UML import elementfactory
from gaphor.UML import uml2
import gc
import weakref, sys
class ElementFactoryTestCase(unittest.TestCase):
def setUp(self):
self.factory = ElementFactory()
self.factory = elementfactory.ElementFactory()
def tearDown(self):
del self.factory
@ -17,34 +36,34 @@ class ElementFactoryTestCase(unittest.TestCase):
def testCreate(self):
ef = self.factory
p = ef.create(Parameter)
assert len(ef.values()) == 1
p = ef.create(uml2.Parameter)
assert len(list(ef.values())) == 1
def testFlush(self):
ef = self.factory
p = ef.create(Parameter)
p = ef.create(uml2.Parameter)
#wp = weakref.ref(p)
assert len(ef.values()) == 1
assert len(list(ef.values())) == 1
ef.flush()
del p
gc.collect()
#assert wp() is None
assert len(ef.values()) == 0, ef.values()
assert len(list(ef.values())) == 0, list(ef.values())
def testWithoutApplication(self):
ef = ElementFactory()
ef = elementfactory.ElementFactory()
p = ef.create(Parameter)
p = ef.create(uml2.Parameter)
assert ef.size() == 1, ef.size()
ef.flush()
assert ef.size() == 0, ef.size()
p = ef.create(Parameter)
p = ef.create(uml2.Parameter)
assert ef.size() == 1, ef.size()
p.unlink()
@ -53,23 +72,23 @@ class ElementFactoryTestCase(unittest.TestCase):
def testUnlink(self):
ef = self.factory
p = ef.create(Parameter)
p = ef.create(uml2.Parameter)
assert len(ef.values()) == 1
assert len(list(ef.values())) == 1
p.unlink()
assert len(ef.values()) == 0, ef.values()
assert len(list(ef.values())) == 0, list(ef.values())
p = ef.create(Parameter)
p = ef.create(uml2.Parameter)
p.defaultValue = 'l'
assert len(ef.values()) == 1
assert len(list(ef.values())) == 1
p.unlink()
del p
assert len(ef.values()) == 0, ef.values()
assert len(list(ef.values())) == 0, list(ef.values())
@ -83,7 +102,7 @@ handled = False
events = []
last_event = None
@component.adapter(IServiceEvent)
@component.adapter(interfaces.IServiceEvent)
def handler(event):
global handled, events, last_event
handled = True
@ -113,31 +132,31 @@ class ElementFactoryServiceTestCase(unittest.TestCase):
def testCreateEvent(self):
ef = self.factory
global handled
p = ef.create(Parameter)
self.assertTrue(IElementCreateEvent.providedBy(last_event) )
p = ef.create(uml2.Parameter)
self.assertTrue(interfaces.IElementCreateEvent.providedBy(last_event) )
self.assertTrue(handled)
def testRemoveEvent(self):
ef = self.factory
global handled
p = ef.create(Parameter)
self.assertTrue(IElementCreateEvent.providedBy(last_event) )
p = ef.create(uml2.Parameter)
self.assertTrue(interfaces.IElementCreateEvent.providedBy(last_event) )
self.assertTrue(handled)
self.clearEvents()
p.unlink()
self.assertTrue(IElementDeleteEvent.providedBy(last_event) )
self.assertTrue(interfaces.IElementDeleteEvent.providedBy(last_event) )
def testModelEvent(self):
ef = self.factory
global handled
ef.notify_model()
self.assertTrue(IModelFactoryEvent.providedBy(last_event) )
self.assertTrue(interfaces.IModelFactoryEvent.providedBy(last_event) )
def testFlushEvent(self):
ef = self.factory
global handled
ef.flush()
self.assertTrue(IFlushFactoryEvent.providedBy(last_event) )
self.assertTrue(interfaces.IFlushFactoryEvent.providedBy(last_event) )
# vim:sw=4:et:ai

View File

@ -1,12 +1,32 @@
from gaphor import UML
from gaphor.application import Application
#!/usr/bin/env python
# Copyright (C) 2009-2017 Arjan Molenaar <gaphor@gmail.com>
# Artur Wroblewski <wrobell@pld-linux.org>
# Dan Yeaw <dan@yeaw.me>
#
# This file is part of Gaphor.
#
# Gaphor is free software: you can redistribute it and/or modify it under the
# terms of the GNU Library General Public License as published by the Free
# Software Foundation, either version 2 of the License, or (at your option)
# any later version.
#
# Gaphor is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
# more details.
#
# You should have received a copy of the GNU Library General Public
# along with Gaphor. If not, see <http://www.gnu.org/licenses/>.
from __future__ import absolute_import
from gaphor.UML import uml2, modelfactory, elementfactory
from gaphor.UML.modelfactory import STEREOTYPE_FMT as fmt
import unittest
class TestCaseBase(unittest.TestCase):
def setUp(self):
self.factory = UML.ElementFactory()
self.factory = elementfactory.ElementFactory()
class StereotypesTestCase(TestCaseBase):
@ -14,134 +34,134 @@ class StereotypesTestCase(TestCaseBase):
def test_stereotype_name(self):
"""Test stereotype name
"""
stereotype = self.factory.create(UML.Stereotype)
stereotype = self.factory.create(uml2.Stereotype)
stereotype.name = 'Test'
self.assertEquals('test', UML.model.stereotype_name(stereotype))
self.assertEquals('test', modelfactory.stereotype_name(stereotype))
stereotype.name = 'TEST'
self.assertEquals('TEST', UML.model.stereotype_name(stereotype))
self.assertEquals('TEST', modelfactory.stereotype_name(stereotype))
stereotype.name = 'T'
self.assertEquals('t', UML.model.stereotype_name(stereotype))
self.assertEquals('t', modelfactory.stereotype_name(stereotype))
stereotype.name = ''
self.assertEquals('', UML.model.stereotype_name(stereotype))
self.assertEquals('', modelfactory.stereotype_name(stereotype))
stereotype.name = None
self.assertEquals('', UML.model.stereotype_name(stereotype))
self.assertEquals('', modelfactory.stereotype_name(stereotype))
def test_stereotypes_conversion(self):
"""Test stereotypes conversion
"""
s1 = self.factory.create(UML.Stereotype)
s2 = self.factory.create(UML.Stereotype)
s3 = self.factory.create(UML.Stereotype)
s1 = self.factory.create(uml2.Stereotype)
s2 = self.factory.create(uml2.Stereotype)
s3 = self.factory.create(uml2.Stereotype)
s1.name = 's1'
s2.name = 's2'
s3.name = 's3'
cls = self.factory.create(UML.Class)
UML.model.apply_stereotype(self.factory, cls, s1)
UML.model.apply_stereotype(self.factory, cls, s2)
UML.model.apply_stereotype(self.factory, cls, s3)
cls = self.factory.create(uml2.Class)
modelfactory.apply_stereotype(self.factory, cls, s1)
modelfactory.apply_stereotype(self.factory, cls, s2)
modelfactory.apply_stereotype(self.factory, cls, s3)
self.assertEquals(fmt % 's1, s2, s3', UML.model.stereotypes_str(cls))
self.assertEquals(fmt % 's1, s2, s3', modelfactory.stereotypes_str(cls))
def test_no_stereotypes(self):
"""Test stereotypes conversion without applied stereotypes
"""
cls = self.factory.create(UML.Class)
self.assertEquals('', UML.model.stereotypes_str(cls))
cls = self.factory.create(uml2.Class)
self.assertEquals('', modelfactory.stereotypes_str(cls))
def test_additional_stereotypes(self):
"""Test additional stereotypes conversion
"""
s1 = self.factory.create(UML.Stereotype)
s2 = self.factory.create(UML.Stereotype)
s3 = self.factory.create(UML.Stereotype)
s1 = self.factory.create(uml2.Stereotype)
s2 = self.factory.create(uml2.Stereotype)
s3 = self.factory.create(uml2.Stereotype)
s1.name = 's1'
s2.name = 's2'
s3.name = 's3'
cls = self.factory.create(UML.Class)
UML.model.apply_stereotype(self.factory, cls, s1)
UML.model.apply_stereotype(self.factory, cls, s2)
UML.model.apply_stereotype(self.factory, cls, s3)
cls = self.factory.create(uml2.Class)
modelfactory.apply_stereotype(self.factory, cls, s1)
modelfactory.apply_stereotype(self.factory, cls, s2)
modelfactory.apply_stereotype(self.factory, cls, s3)
result = UML.model.stereotypes_str(cls, ('test',))
result = modelfactory.stereotypes_str(cls, ('test',))
self.assertEquals(fmt % 'test, s1, s2, s3', result)
def test_just_additional_stereotypes(self):
"""Test additional stereotypes conversion without applied stereotypes
"""
cls = self.factory.create(UML.Class)
cls = self.factory.create(uml2.Class)
result = UML.model.stereotypes_str(cls, ('test',))
result = modelfactory.stereotypes_str(cls, ('test',))
self.assertEquals(fmt % 'test', result)
def test_getting_stereotypes(self):
"""Test getting possible stereotypes
"""
cls = self.factory.create(UML.Class)
cls = self.factory.create(uml2.Class)
cls.name = 'Class'
st1 = self.factory.create(UML.Stereotype)
st1 = self.factory.create(uml2.Stereotype)
st1.name = 'st1'
st2 = self.factory.create(UML.Stereotype)
st2 = self.factory.create(uml2.Stereotype)
st2.name = 'st2'
# first extend with st2, to check sorting
UML.model.extend_with_stereotype(self.factory, cls, st2)
UML.model.extend_with_stereotype(self.factory, cls, st1)
modelfactory.extend_with_stereotype(self.factory, cls, st2)
modelfactory.extend_with_stereotype(self.factory, cls, st1)
c1 = self.factory.create(UML.Class)
result = tuple(st.name for st in UML.model.get_stereotypes(self.factory, c1))
c1 = self.factory.create(uml2.Class)
result = tuple(st.name for st in modelfactory.get_stereotypes(self.factory, c1))
self.assertEquals(('st1', 'st2'), result)
def test_getting_stereotypes_unique(self):
"""Test if possible stereotypes are unique
"""
cls1 = self.factory.create(UML.Class)
cls1 = self.factory.create(uml2.Class)
cls1.name = 'Class'
cls2 = self.factory.create(UML.Class)
cls2 = self.factory.create(uml2.Class)
cls2.name = 'Component'
st1 = self.factory.create(UML.Stereotype)
st1 = self.factory.create(uml2.Stereotype)
st1.name = 'st1'
st2 = self.factory.create(UML.Stereotype)
st2 = self.factory.create(uml2.Stereotype)
st2.name = 'st2'
# first extend with st2, to check sorting
UML.model.extend_with_stereotype(self.factory, cls1, st2)
UML.model.extend_with_stereotype(self.factory, cls1, st1)
modelfactory.extend_with_stereotype(self.factory, cls1, st2)
modelfactory.extend_with_stereotype(self.factory, cls1, st1)
UML.model.extend_with_stereotype(self.factory, cls2, st1)
UML.model.extend_with_stereotype(self.factory, cls2, st2)
modelfactory.extend_with_stereotype(self.factory, cls2, st1)
modelfactory.extend_with_stereotype(self.factory, cls2, st2)
c1 = self.factory.create(UML.Component)
result = tuple(st.name for st in UML.model.get_stereotypes(self.factory, c1))
c1 = self.factory.create(uml2.Component)
result = tuple(st.name for st in modelfactory.get_stereotypes(self.factory, c1))
self.assertEquals(('st1', 'st2'), result)
def test_finding_stereotype_instances(self):
"""Test finding stereotype instances
"""
s1 = self.factory.create(UML.Stereotype)
s2 = self.factory.create(UML.Stereotype)
s1 = self.factory.create(uml2.Stereotype)
s2 = self.factory.create(uml2.Stereotype)
s1.name = 's1'
s2.name = 's2'
c1 = self.factory.create(UML.Class)
c2 = self.factory.create(UML.Class)
UML.model.apply_stereotype(self.factory, c1, s1)
UML.model.apply_stereotype(self.factory, c1, s2)
UML.model.apply_stereotype(self.factory, c2, s1)
c1 = self.factory.create(uml2.Class)
c2 = self.factory.create(uml2.Class)
modelfactory.apply_stereotype(self.factory, c1, s1)
modelfactory.apply_stereotype(self.factory, c1, s2)
modelfactory.apply_stereotype(self.factory, c2, s1)
result = [e.classifier[0].name for e in UML.model.find_instances(self.factory, s1)]
result = [e.classifier[0].name for e in modelfactory.find_instances(self.factory, s1)]
self.assertEquals(2, len(result))
self.assertTrue('s1' in result, result)
self.assertFalse('s2' in result, result)
@ -155,16 +175,16 @@ class AssociationTestCase(TestCaseBase):
def test_creation(self):
"""Test association creation
"""
c1 = self.factory.create(UML.Class)
c2 = self.factory.create(UML.Class)
assoc = UML.model.create_association(self.factory, c1, c2)
c1 = self.factory.create(uml2.Class)
c2 = self.factory.create(uml2.Class)
assoc = modelfactory.create_association(self.factory, c1, c2)
types = [p.type for p in assoc.memberEnd]
self.assertTrue(c1 in types, assoc.memberEnd)
self.assertTrue(c2 in types, assoc.memberEnd)
c1 = self.factory.create(UML.Interface)
c2 = self.factory.create(UML.Interface)
assoc = UML.model.create_association(self.factory, c1, c2)
c1 = self.factory.create(uml2.Interface)
c2 = self.factory.create(uml2.Interface)
assoc = modelfactory.create_association(self.factory, c1, c2)
types = [p.type for p in assoc.memberEnd]
self.assertTrue(c1 in types, assoc.memberEnd)
self.assertTrue(c2 in types, assoc.memberEnd)
@ -178,15 +198,15 @@ class AssociationEndNavigabilityTestCase(TestCaseBase):
def test_attribute_navigability(self):
"""Test navigable attribute of a class or an interface
"""
c1 = self.factory.create(UML.Class)
c2 = self.factory.create(UML.Class)
assoc = UML.model.create_association(self.factory, c1, c2)
c1 = self.factory.create(uml2.Class)
c2 = self.factory.create(uml2.Class)
assoc = modelfactory.create_association(self.factory, c1, c2)
end = assoc.memberEnd[0]
assert end.type is c1
assert end.type is c1
UML.model.set_navigability(assoc, end, True)
modelfactory.set_navigability(assoc, end, True)
# class/interface navigablity, Association.navigableOwnedEnd not
# involved
@ -196,7 +216,7 @@ class AssociationEndNavigabilityTestCase(TestCaseBase):
self.assertTrue(end.navigability is True)
# uknown navigability
UML.model.set_navigability(assoc, end, None)
modelfactory.set_navigability(assoc, end, None)
self.assertTrue(end not in assoc.navigableOwnedEnd)
self.assertTrue(end in assoc.ownedEnd)
self.assertTrue(end not in c2.ownedAttribute)
@ -204,7 +224,7 @@ class AssociationEndNavigabilityTestCase(TestCaseBase):
self.assertTrue(end.navigability is None)
# non-navigability
UML.model.set_navigability(assoc, end, False)
modelfactory.set_navigability(assoc, end, False)
self.assertTrue(end not in assoc.navigableOwnedEnd)
self.assertTrue(end not in assoc.ownedEnd)
self.assertTrue(end not in c2.ownedAttribute)
@ -212,14 +232,14 @@ class AssociationEndNavigabilityTestCase(TestCaseBase):
self.assertTrue(end.navigability is False)
# check other navigability change possibilities
UML.model.set_navigability(assoc, end, None)
modelfactory.set_navigability(assoc, end, None)
self.assertTrue(end not in assoc.navigableOwnedEnd)
self.assertTrue(end in assoc.ownedEnd)
self.assertTrue(end not in c2.ownedAttribute)
self.assertTrue(end.owner is assoc)
self.assertTrue(end.navigability is None)
UML.model.set_navigability(assoc, end, True)
modelfactory.set_navigability(assoc, end, True)
self.assertTrue(end not in assoc.navigableOwnedEnd)
self.assertTrue(end not in assoc.ownedEnd)
self.assertTrue(end in c2.ownedAttribute)
@ -230,14 +250,14 @@ class AssociationEndNavigabilityTestCase(TestCaseBase):
def test_relationship_navigability(self):
"""Test navigable relationship of a classifier
"""
n1 = self.factory.create(UML.Node)
n2 = self.factory.create(UML.Node)
assoc = UML.model.create_association(self.factory, n1, n2)
n1 = self.factory.create(uml2.Node)
n2 = self.factory.create(uml2.Node)
assoc = modelfactory.create_association(self.factory, n1, n2)
end = assoc.memberEnd[0]
assert end.type is n1
UML.model.set_navigability(assoc, end, True)
modelfactory.set_navigability(assoc, end, True)
# class/interface navigablity, Association.navigableOwnedEnd not
# involved
@ -246,24 +266,24 @@ class AssociationEndNavigabilityTestCase(TestCaseBase):
self.assertTrue(end.navigability is True)
# uknown navigability
UML.model.set_navigability(assoc, end, None)
modelfactory.set_navigability(assoc, end, None)
self.assertTrue(end not in assoc.navigableOwnedEnd)
self.assertTrue(end in assoc.ownedEnd)
self.assertTrue(end.navigability is None)
# non-navigability
UML.model.set_navigability(assoc, end, False)
modelfactory.set_navigability(assoc, end, False)
self.assertTrue(end not in assoc.navigableOwnedEnd)
self.assertTrue(end not in assoc.ownedEnd)
self.assertTrue(end.navigability is False)
# check other navigability change possibilities
UML.model.set_navigability(assoc, end, None)
modelfactory.set_navigability(assoc, end, None)
self.assertTrue(end not in assoc.navigableOwnedEnd)
self.assertTrue(end in assoc.ownedEnd)
self.assertTrue(end.navigability is None)
UML.model.set_navigability(assoc, end, True)
modelfactory.set_navigability(assoc, end, True)
self.assertTrue(end in assoc.navigableOwnedEnd)
self.assertTrue(end not in assoc.ownedEnd)
self.assertTrue(end.navigability is True)
@ -277,30 +297,30 @@ class DependencyTypeTestCase(TestCaseBase):
def test_usage(self):
"""Test automatic dependency: usage
"""
cls = self.factory.create(UML.Class)
iface = self.factory.create(UML.Interface)
dt = UML.model.dependency_type(cls, iface)
self.assertEquals(UML.Usage, dt)
cls = self.factory.create(uml2.Class)
iface = self.factory.create(uml2.Interface)
dt = modelfactory.dependency_type(cls, iface)
self.assertEquals(uml2.Usage, dt)
def test_usage_by_component(self):
"""Test automatic dependency: usage (by component)
"""
c = self.factory.create(UML.Component)
iface = self.factory.create(UML.Interface)
dt = UML.model.dependency_type(c, iface)
c = self.factory.create(uml2.Component)
iface = self.factory.create(uml2.Interface)
dt = modelfactory.dependency_type(c, iface)
# it should be usage not realization (interface is classifier as
# well)
self.assertEquals(UML.Usage, dt)
self.assertEquals(uml2.Usage, dt)
def test_realization(self):
"""Test automatic dependency: realization
"""
c = self.factory.create(UML.Component)
cls = self.factory.create(UML.Class)
dt = UML.model.dependency_type(c, cls)
self.assertEquals(UML.Realization, dt)
c = self.factory.create(uml2.Component)
cls = self.factory.create(uml2.Class)
dt = modelfactory.dependency_type(c, cls)
self.assertEquals(uml2.Realization, dt)
class MessageTestCase(TestCaseBase):
@ -310,11 +330,11 @@ class MessageTestCase(TestCaseBase):
def test_create(self):
"""Test message creation
"""
m = self.factory.create(UML.Message)
send = self.factory.create(UML.MessageOccurrenceSpecification)
receive = self.factory.create(UML.MessageOccurrenceSpecification)
sl = self.factory.create(UML.Lifeline)
rl = self.factory.create(UML.Lifeline)
m = self.factory.create(uml2.Message)
send = self.factory.create(uml2.MessageOccurrenceSpecification)
receive = self.factory.create(uml2.MessageOccurrenceSpecification)
sl = self.factory.create(uml2.Lifeline)
rl = self.factory.create(uml2.Lifeline)
send.covered = sl
receive.covered = rl
@ -322,8 +342,8 @@ class MessageTestCase(TestCaseBase):
m.sendEvent = send
m.receiveEvent = receive
m1 = UML.model.create_message(self.factory, m, False)
m2 = UML.model.create_message(self.factory, m, True)
m1 = modelfactory.create_message(self.factory, m, False)
m2 = modelfactory.create_message(self.factory, m, True)
self.assertTrue(m1.sendEvent.covered is sl)
self.assertTrue(m1.receiveEvent.covered is rl)

View File

@ -1,5 +1,23 @@
#!/usr/bin/env python
# Copyright (C) 2007-2017 Arjan Molenaar <gaphor@gmail.com>
# Dan Yeaw <dan@yeaw.me>
#
# This file is part of Gaphor.
#
# Gaphor is free software: you can redistribute it and/or modify it under the
# terms of the GNU Library General Public License as published by the Free
# Software Foundation, either version 2 of the License, or (at your option)
# any later version.
#
# Gaphor is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
# more details.
#
# You should have received a copy of the GNU Library General Public
# along with Gaphor. If not, see <http://www.gnu.org/licenses/>.
from __future__ import absolute_import
import unittest
from zope import component
from gaphor.application import Application
@ -85,7 +103,7 @@ class PropertiesTestCase(unittest.TestCase):
c = C()
try:
a.one = c
except Exception, e:
except Exception as e:
pass #ok print 'exception caught:', e
else:
assert a.one is not c
@ -339,7 +357,7 @@ class PropertiesTestCase(unittest.TestCase):
import types
class A(Element): pass
A.a = attribute('a', types.StringType, 'default')
A.a = attribute('a', bytes, 'default')
a = A()
assert a.a == 'default', a.a
@ -382,7 +400,7 @@ class PropertiesTestCase(unittest.TestCase):
self.notified = name
A.assoc = association('assoc', A)
A.attr = attribute('attr', types.StringType, 'default')
A.attr = attribute('attr', bytes, 'default')
A.enum = enumeration('enum', ('one', 'two'), 'one')
a = A()

View File

@ -1,13 +1,34 @@
#!/usr/bin/env python
# Copyright (C) 2003-2017 Adam Boduch <adam.boduch@gmail.com>
# Arjan Molenaar <gaphor@gmail.com>
# Dan Yeaw <dan@yeaw.me>
#
# This file is part of Gaphor.
#
# Gaphor is free software: you can redistribute it and/or modify it under the
# terms of the GNU Library General Public License as published by the Free
# Software Foundation, either version 2 of the License, or (at your option)
# any later version.
#
# Gaphor is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
# more details.
#
# You should have received a copy of the GNU Library General Public
# along with Gaphor. If not, see <http://www.gnu.org/licenses/>.
from __future__ import absolute_import
from __future__ import print_function
import unittest
import gaphor.UML as UML
from gaphor.UML import uml2, elementfactory, modelfactory, umllex
class ClassesTestCase(unittest.TestCase):
def setUp(self):
self.factory = UML.ElementFactory()
self.factory = elementfactory.ElementFactory()
def tearDown(self):
@ -19,7 +40,7 @@ class ClassesTestCase(unittest.TestCase):
try:
element = self.factory.create(UML.Association)
element = self.factory.create(uml2.Association)
except AttributeError:
@ -27,8 +48,8 @@ class ClassesTestCase(unittest.TestCase):
self.assertFalse(element.isDerived, 'The isDerived property should default to False - %s' % element.isDerived)
property1 = self.factory.create(UML.Property)
property2 = self.factory.create(UML.Property)
property1 = self.factory.create(uml2.Property)
property2 = self.factory.create(uml2.Property)
element.memberEnd = property1
element.memberEnd = property2
@ -47,7 +68,7 @@ class ClassesTestCase(unittest.TestCase):
# def test_association_class(self):
# try:
# element = self.factory.create(UML.AssociationClass)
# element = self.factory.create(uml2.AssociationClass)
# except AttributeError:
# self.fail('AssociationClass elements are not part of the meta-model')
@ -57,14 +78,14 @@ class ClassesTestCase(unittest.TestCase):
try:
element = self.factory.create(UML.Class)
element = self.factory.create(uml2.Class)
except AttributeError:
self.fail('Class elements are not part of the meta-model')
property1 = self.factory.create(UML.Property)
operation1 = self.factory.create(UML.Operation)
property1 = self.factory.create(uml2.Property)
operation1 = self.factory.create(uml2.Operation)
element.ownedAttribute = property1
element.ownedOperation = operation1
@ -81,7 +102,7 @@ class ClassesTestCase(unittest.TestCase):
try:
element = self.factory.create(UML.Comment)
element = self.factory.create(uml2.Comment)
except AttributeError:
@ -91,7 +112,7 @@ class ClassesTestCase(unittest.TestCase):
self.assertTrue(element.body == 'Comment body', 'Incorrect comment body - %s' % element.body)
annotatedElement = self.factory.create(UML.Class)
annotatedElement = self.factory.create(uml2.Class)
element.annotatedElement = annotatedElement
@ -103,13 +124,13 @@ class ClassesTestCase(unittest.TestCase):
try:
element = self.factory.create(UML.Constraint)
element = self.factory.create(uml2.Constraint)
except AttributeError:
self.fail('Constraint elements are not part of the meta-model')
constrainedElement = self.factory.create(UML.Class)
constrainedElement = self.factory.create(uml2.Class)
element.constrainedElement = constrainedElement
element.specification = 'Constraint specification'
@ -123,14 +144,14 @@ class ClassesTestCase(unittest.TestCase):
try:
element = self.factory.create(UML.Dependency)
element = self.factory.create(uml2.Dependency)
except AttributeError:
self.fail('Dependency elements are not part of the meta-model')
client = self.factory.create(UML.Package)
supplier = self.factory.create(UML.Package)
client = self.factory.create(uml2.Package)
supplier = self.factory.create(uml2.Package)
element.client = client
element.supplier = supplier
@ -142,7 +163,7 @@ class ClassesTestCase(unittest.TestCase):
try:
element = self.factory.create(UML.ElementImport)
element = self.factory.create(uml2.ElementImport)
except AttributeError:
@ -152,7 +173,7 @@ class ClassesTestCase(unittest.TestCase):
try:
element = self.factory.create(UML.Enumeration)
element = self.factory.create(uml2.Enumeration)
except AttributeError:
@ -162,7 +183,7 @@ class ClassesTestCase(unittest.TestCase):
try:
element = self.factory.create(UML.Generalization)
element = self.factory.create(uml2.Generalization)
except AttributeError:
@ -172,7 +193,7 @@ class ClassesTestCase(unittest.TestCase):
try:
element = self.factory.create(UML.Interface)
element = self.factory.create(uml2.Interface)
except AttributeError:
@ -182,7 +203,7 @@ class ClassesTestCase(unittest.TestCase):
try:
element = self.factory.create(UML.Namespace)
element = self.factory.create(uml2.Namespace)
except AttributeError:
@ -192,7 +213,7 @@ class ClassesTestCase(unittest.TestCase):
try:
element = self.factory.create(UML.Operation)
element = self.factory.create(uml2.Operation)
except AttributeError:
@ -202,7 +223,7 @@ class ClassesTestCase(unittest.TestCase):
try:
element = self.factory.create(UML.Package)
element = self.factory.create(uml2.Package)
except AttributeError:
@ -212,7 +233,7 @@ class ClassesTestCase(unittest.TestCase):
try:
element = self.factory.create(UML.Parameter)
element = self.factory.create(uml2.Parameter)
except AttributeError:
@ -222,7 +243,7 @@ class ClassesTestCase(unittest.TestCase):
try:
element = self.factory.create(UML.Property)
element = self.factory.create(uml2.Property)
except AttributeError:
@ -232,7 +253,7 @@ class ClassesTestCase(unittest.TestCase):
try:
element = self.factory.create(UML.Realization)
element = self.factory.create(uml2.Realization)
except AttributeError:
@ -242,26 +263,26 @@ class ClassesTestCase(unittest.TestCase):
class Uml2TestCase(unittest.TestCase):
def test_ids(self):
factory = UML.ElementFactory()
c = factory.create(UML.Class)
factory = elementfactory.ElementFactory()
c = factory.create(uml2.Class)
assert c.id
p = factory.create_as(UML.Class, id=False)
p = factory.create_as(uml2.Class, id=False)
assert p.id is False, p.id
def test1(self):
factory = UML.ElementFactory()
c = factory.create(UML.Class)
p = factory.create(UML.Package)
factory = elementfactory.ElementFactory()
c = factory.create(uml2.Class)
p = factory.create(uml2.Package)
c.package = p
self.assertEquals(c.package, p)
self.assertEquals(c.namespace, p)
self.failUnless(c in p.ownedElement)
def testOwnedMember_Unlink(self):
factory = UML.ElementFactory()
c = factory.create(UML.Class)
p = factory.create(UML.Package)
factory = elementfactory.ElementFactory()
c = factory.create(uml2.Class)
p = factory.create(uml2.Package)
c.package = p
c.unlink()
@ -291,7 +312,7 @@ class Uml2TestCase(unittest.TestCase):
# # TODO: test signal handling
def test_property_is_composite(self):
p = UML.Property()
p = uml2.Property()
assert p.isComposite == False, p.isComposite
p.aggregation = 'shared'
assert p.isComposite == False, p.isComposite
@ -300,12 +321,12 @@ class Uml2TestCase(unittest.TestCase):
def test_association_endType(self):
factory = UML.ElementFactory()
c1 = UML.Class()
c2 = UML.Class()
a = UML.Association()
a.memberEnd = UML.Property()
a.memberEnd = UML.Property()
factory = elementfactory.ElementFactory()
c1 = uml2.Class()
c2 = uml2.Class()
a = uml2.Association()
a.memberEnd = uml2.Property()
a.memberEnd = uml2.Property()
a.memberEnd[0].type = c1
a.memberEnd[1].type = c2
c1.ownedAttribute = a.memberEnd[0]
@ -314,7 +335,7 @@ class Uml2TestCase(unittest.TestCase):
assert c1 in a.endType
assert c2 in a.endType
c3 = UML.Class()
c3 = uml2.Class()
a.memberEnd[1].type = c3
assert c1 in a.endType
@ -323,29 +344,29 @@ class Uml2TestCase(unittest.TestCase):
def test_property_navigability(self):
factory = UML.ElementFactory()
p = factory.create(UML.Property)
factory = elementfactory.ElementFactory()
p = factory.create(uml2.Property)
assert p.navigability is None
c1 = factory.create(UML.Class)
c2 = factory.create(UML.Class)
a = UML.model.create_association(factory, c1, c2)
c1 = factory.create(uml2.Class)
c2 = factory.create(uml2.Class)
a = modelfactory.create_association(factory, c1, c2)
assert a.memberEnd[0].navigability is None
assert a.memberEnd[1].navigability is None
UML.model.set_navigability(a, a.memberEnd[0], True)
modelfactory.set_navigability(a, a.memberEnd[0], True)
assert a.memberEnd[0].navigability is True
assert a.memberEnd[1].navigability is None
UML.model.set_navigability(a, a.memberEnd[0], False)
modelfactory.set_navigability(a, a.memberEnd[0], False)
assert a.memberEnd[0].navigability is False
assert a.memberEnd[1].navigability is None
def test_namedelement_qualifiedname(self):
factory = UML.ElementFactory()
p = factory.create(UML.Package)
factory = elementfactory.ElementFactory()
p = factory.create(uml2.Package)
p.name = 'Package'
c = factory.create(UML.Class)
c = factory.create(uml2.Class)
c.name = 'Class'
self.assertEquals(('Class',), c.qualifiedName)
@ -356,42 +377,42 @@ class Uml2TestCase(unittest.TestCase):
def test_extension_metaclass(self):
factory = UML.ElementFactory()
c = factory.create(UML.Class)
factory = elementfactory.ElementFactory()
c = factory.create(uml2.Class)
c.name = 'Class'
s = factory.create(UML.Stereotype)
s = factory.create(uml2.Stereotype)
s.name = 'Stereotype'
e = UML.model.create_extension(factory, c, s)
e = modelfactory.create_extension(factory, c, s)
self.assertEquals(c, e.metaclass)
def test_metaclass_extension(self):
factory = UML.ElementFactory()
c = factory.create(UML.Class)
factory = elementfactory.ElementFactory()
c = factory.create(uml2.Class)
c.name = 'Class'
s = factory.create(UML.Stereotype)
s = factory.create(uml2.Stereotype)
s.name = 'Stereotype'
self.assertEquals([], c.extension)
self.assertEquals([], s.extension)
e = UML.model.create_extension(factory, c, s)
e = modelfactory.create_extension(factory, c, s)
print e.memberEnd
print(e.memberEnd)
self.assertEquals([e], c.extension)
self.assertEquals([], s.extension)
assert e.ownedEnd.type is s
def test_operation_parameter_deletion(self):
factory = UML.ElementFactory()
factory = elementfactory.ElementFactory()
self.assertEquals(0, len(factory.lselect()))
c = factory.create(UML.Class)
c = factory.create(uml2.Class)
c.name = 'Class'
o = factory.create(UML.Operation)
o = factory.create(uml2.Operation)
c.ownedOperation = o
UML.parse(o, 'a(x: int, y: int)')
umllex.parse(o, 'a(x: int, y: int)')
c.unlink()

View File

@ -1,7 +1,28 @@
#!/usr/bin/env python
# Copyright (C) 2010-2017 Arjan Molenaar <gaphor@gmail.com>
# Artur Wroblewski <wrobell@pld-linux.org>
# Dan Yeaw <dan@yeaw.me>
#
# This file is part of Gaphor.
#
# Gaphor is free software: you can redistribute it and/or modify it under the
# terms of the GNU Library General Public License as published by the Free
# Software Foundation, either version 2 of the License, or (at your option)
# any later version.
#
# Gaphor is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
# more details.
#
# You should have received a copy of the GNU Library General Public
# along with Gaphor. If not, see <http://www.gnu.org/licenses/>.
"""
Formatting of UML model elements into text tests.
"""
from __future__ import absolute_import
import unittest
from gaphor.application import Application

View File

@ -1,13 +1,33 @@
#!/usr/bin/env python
# Copyright (C) 2007-2017 Arjan Molenaar <gaphor@gmail.com>
# Artur Wroblewski <wrobell@pld-linux.org>
# Dan Yeaw <dan@yeaw.me>
#
# This file is part of Gaphor.
#
# Gaphor is free software: you can redistribute it and/or modify it under the
# terms of the GNU Library General Public License as published by the Free
# Software Foundation, either version 2 of the License, or (at your option)
# any later version.
#
# Gaphor is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
# more details.
#
# You should have received a copy of the GNU Library General Public
# along with Gaphor. If not, see <http://www.gnu.org/licenses/>.
"""
Parsing of UML model elements from string tests.
"""
from __future__ import absolute_import
import unittest
from gaphor.application import Application
from gaphor.UML.elementfactory import ElementFactory
from gaphor.UML.umllex import parse
from gaphor.UML.umllex import attribute_pat, operation_pat, parameter_pat
from gaphor import UML
from gaphor.UML import uml2
from gaphor.UML.umllex import parse
def dump_prop(prop):
m = attribute_pat.match(prop)
@ -55,8 +75,8 @@ class AttributeTestCase(unittest.TestCase):
def test_parse_property_simple(self):
"""Test simple property parsing
"""
a = factory.create(UML.Property)
UML.parse(a, 'myattr')
a = factory.create(uml2.Property)
parse(a, 'myattr')
self.assertFalse(a.isDerived)
self.assertEquals('myattr', a.name)
self.assertTrue(a.typeValue is None, a.typeValue)
@ -68,9 +88,9 @@ class AttributeTestCase(unittest.TestCase):
def test_parse_property_complex(self):
"""Test complex property parsing
"""
a = factory.create(UML.Property)
a = factory.create(uml2.Property)
UML.parse(a,'+ / name : str[0..*] = "aap" { static }')
parse(a,'+ / name : str[0..*] = "aap" { static }')
self.assertEquals('public', a.visibility)
self.assertTrue(a.isDerived)
self.assertEquals('name', a.name)
@ -83,9 +103,9 @@ class AttributeTestCase(unittest.TestCase):
def test_parse_property_invalid(self):
"""Test parsing property with invalid syntax
"""
a = factory.create(UML.Property)
a = factory.create(uml2.Property)
UML.parse(a, '+ name = str[*] = "aap" { static }')
parse(a, '+ name = str[*] = "aap" { static }')
self.assertEquals('+ name = str[*] = "aap" { static }', a.name)
self.assertFalse(a.isDerived)
self.assertTrue(not a.typeValue)
@ -108,11 +128,11 @@ class AssociationEndTestCase(unittest.TestCase):
def test_parse_association_end(self):
"""Test parsing of association end
"""
a = factory.create(UML.Association)
p = factory.create(UML.Property)
a = factory.create(uml2.Association)
p = factory.create(uml2.Property)
p.association = a
UML.parse(p, 'end')
parse(p, 'end')
self.assertEquals('end', p.name)
self.assertTrue(not p.typeValue)
self.assertTrue(not p.lowerValue)
@ -123,10 +143,10 @@ class AssociationEndTestCase(unittest.TestCase):
def test_parse_multiplicity(self):
"""Test parsing of multiplicity
"""
a = factory.create(UML.Association)
p = factory.create(UML.Property)
a = factory.create(uml2.Association)
p = factory.create(uml2.Property)
p.association = a
UML.parse(p, '0..2 { tag }')
parse(p, '0..2 { tag }')
self.assertTrue(p.name is None)
self.assertTrue(not p.typeValue)
self.assertEquals('0', p.lowerValue)
@ -137,10 +157,10 @@ class AssociationEndTestCase(unittest.TestCase):
def test_parse_multiplicity2(self):
"""Test parsing of multiplicity with multiline constraints
"""
a = factory.create(UML.Association)
p = factory.create(UML.Property)
a = factory.create(uml2.Association)
p = factory.create(uml2.Property)
p.association = a
UML.parse(p, '0..2 { tag1, \ntag2}')
parse(p, '0..2 { tag1, \ntag2}')
self.assertTrue(p.name is None)
self.assertTrue(not p.typeValue)
self.assertEquals('0', p.lowerValue)
@ -151,10 +171,10 @@ class AssociationEndTestCase(unittest.TestCase):
def test_parse_derived_end(self):
"""Test parsing derived association end
"""
a = factory.create(UML.Association)
p = factory.create(UML.Property)
a = factory.create(uml2.Association)
p = factory.create(uml2.Property)
p.association = a
UML.parse(p, '-/end[*] { mytag}')
parse(p, '-/end[*] { mytag}')
self.assertEquals('private', p.visibility)
self.assertTrue(p.isDerived)
self.assertEquals('end', p.name)
@ -178,8 +198,8 @@ class OperationTestCase(unittest.TestCase):
def test_parse_operation(self):
"""Test parsing simple operation
"""
o = factory.create(UML.Operation)
UML.parse(o, 'myfunc()')
o = factory.create(uml2.Operation)
parse(o, 'myfunc()')
self.assertEquals('myfunc', o.name)
self.assertTrue(not o.returnResult[0].typeValue)
self.assertFalse(o.formalParameter)
@ -188,8 +208,8 @@ class OperationTestCase(unittest.TestCase):
def test_parse_operation_return(self):
"""Test parsing operation with return value
"""
o = factory.create(UML.Operation)
UML.parse(o, '+ myfunc(): int')
o = factory.create(uml2.Operation)
parse(o, '+ myfunc(): int')
self.assertEquals('myfunc', o.name)
self.assertEquals('int', o.returnResult[0].typeValue)
self.assertEquals('public', o.visibility)
@ -199,8 +219,8 @@ class OperationTestCase(unittest.TestCase):
def test_parse_operation_2_params(self):
"""Test parsing of operation with two parameters
"""
o = factory.create(UML.Operation)
UML.parse(o, '# myfunc2 (a: str, b: int = 3 { static}): float')
o = factory.create(uml2.Operation)
parse(o, '# myfunc2 (a: str, b: int = 3 { static}): float')
self.assertEquals('myfunc2', o.name)
self.assertEquals('float', o.returnResult[0].typeValue)
self.assertEquals('protected', o.visibility)
@ -216,8 +236,8 @@ class OperationTestCase(unittest.TestCase):
def test_parse_operation_1_param(self):
"""Test parsing of operation with one parameter
"""
o = factory.create(UML.Operation)
UML.parse(o, '- myfunc2 (a: node): double')
o = factory.create(uml2.Operation)
parse(o, '- myfunc2 (a: node): double')
self.assertEquals('myfunc2', o.name)
self.assertEquals('double', o.returnResult[0].typeValue)
self.assertEquals('private', o.visibility)
@ -230,8 +250,8 @@ class OperationTestCase(unittest.TestCase):
def test_parse_operation_invalid_syntax(self):
"""Test operation parsing with invalid syntax
"""
o = factory.create(UML.Operation)
UML.parse(o, '- myfunc2: myType2')
o = factory.create(uml2.Operation)
parse(o, '- myfunc2: myType2')
self.assertEquals('- myfunc2: myType2', o.name)

View File

@ -1,7 +1,28 @@
#!/usr/bin/env python
# Copyright (C) 2010-2017 Arjan Molenaar <gaphor@gmail.com>
# Artur Wroblewski <wrobell@pld-linux.org>
# Dan Yeaw <dan@yeaw.me>
#
# This file is part of Gaphor.
#
# Gaphor is free software: you can redistribute it and/or modify it under the
# terms of the GNU Library General Public License as published by the Free
# Software Foundation, either version 2 of the License, or (at your option)
# any later version.
#
# Gaphor is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
# more details.
#
# You should have received a copy of the GNU Library General Public
# along with Gaphor. If not, see <http://www.gnu.org/licenses/>.
"""
Formatting of UML elements like attributes, operations, stereotypes, etc.
"""
from __future__ import absolute_import
import re
from cStringIO import StringIO
from simplegeneric import generic

View File

@ -1,3 +1,23 @@
#!/usr/bin/env python
# Copyright (C) 2003-2017 Arjan Molenaar <gaphor@gmail.com>
# Artur Wroblewski <wrobell@pld-linux.org>
# Dan Yeaw <dan@yeaw.me>
#
# This file is part of Gaphor.
#
# Gaphor is free software: you can redistribute it and/or modify it under the
# terms of the GNU Library General Public License as published by the Free
# Software Foundation, either version 2 of the License, or (at your option)
# any later version.
#
# Gaphor is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
# more details.
#
# You should have received a copy of the GNU Library General Public
# along with Gaphor. If not, see <http://www.gnu.org/licenses/>.
"""
Lexical analizer for attributes and operations.
@ -7,15 +27,17 @@ The regular expressions are constructed based on a series of
attribute/operation.
"""
from __future__ import absolute_import
from six.moves import map
__all__ = [
'parse_property', 'parse_operation',
]
'parse_property', 'parse_operation',
]
import re
from simplegeneric import generic
#from gaphor.UML import uml2 as UML
import uml2 as UML
from gaphor.UML.uml2 import Property, NamedElement, Operation, Parameter
@generic
@ -24,7 +46,7 @@ def parse(el, text):
Parser for an UML element.
"""
raise NotImplementedError('Parsing routine for type %s not implemented yet' \
% type(el))
% type(el))
# Visibility (optional) ::= '+' | '-' | '#'
@ -61,16 +83,20 @@ dir_subpat = r'\s*((?P<dir>in|out|inout)\s)?'
# Some trailing garbage => no valid syntax...
garbage_subpat = r'\s*(?P<garbage>.*)'
def compile(regex):
return re.compile(regex, re.MULTILINE | re.S)
# Attribute:
# [+-#] [/] name [: type[\[mult\]]] [= default] [{ tagged values }]
attribute_pat = compile(r'^' + vis_subpat + derived_subpat + name_subpat + type_subpat + default_subpat + tags_subpat + garbage_subpat)
attribute_pat = compile(
r'^' + vis_subpat + derived_subpat + name_subpat + type_subpat + default_subpat + tags_subpat + garbage_subpat)
# Association end name:
# [[+-#] [/] name [\[mult\]]] [{ tagged values }]
association_end_name_pat = compile(r'^' + '(' + vis_subpat + derived_subpat + name_subpat + mult_subpat + ')?' + tags_subpat + garbage_subpat)
association_end_name_pat = compile(
r'^' + '(' + vis_subpat + derived_subpat + name_subpat + mult_subpat + ')?' + tags_subpat + garbage_subpat)
# Association end multiplicity:
# [mult] [{ tagged values }]
@ -88,6 +114,7 @@ parameter_pat = compile(r'^' + dir_subpat + name_subpat + type_subpat + default_
# [name] [: type]
lifeline_pat = compile('^' + name_subpat + type_subpat + garbage_subpat)
def _set_visibility(el, vis):
if vis == '+':
el.visibility = 'public'
@ -103,6 +130,7 @@ def _set_visibility(el, vis):
except AttributeError:
pass
def parse_attribute(el, s):
"""
Parse string s in the property. Tagged values, multiplicity and stuff
@ -132,8 +160,8 @@ def parse_attribute(el, s):
el.upperValue = g('mult_u')
el.defaultValue = g('default')
# Skip tags: should do something with stereotypes?
#tags = g('tags')
#if tags:
# tags = g('tags')
# if tags:
# for t in map(str.strip, tags.split(',')):
# tv = create(UML.LiteralSpecification)
# tv.value = t
@ -164,8 +192,8 @@ def parse_association_end(el, s):
g = m.group
el.lowerValue = g('mult_l')
el.upperValue = g('mult_u')
#tags = g('tags')
#if tags:
# tags = g('tags')
# if tags:
# for t in map(str.strip, tags.split(',')):
# tv = create(UML.LiteralSpecification)
# tv.value = t
@ -190,16 +218,17 @@ def parse_association_end(el, s):
el.lowerValue = None
el.upperValue = g('mult_u')
#tags = g('tags')
#if tags:
# while el.taggedValue:
# el.taggedValue[0].unlink()
# for t in map(str.strip, tags.split(',')):
# tv = create(UML.LiteralSpecification)
# tv.value = t
# el.taggedValue = tv
# tags = g('tags')
# if tags:
# while el.taggedValue:
# el.taggedValue[0].unlink()
# for t in map(str.strip, tags.split(',')):
# tv = create(UML.LiteralSpecification)
# tv.value = t
# el.taggedValue = tv
@parse.when_type(UML.Property)
@parse.when_type(Property)
def parse_property(el, s):
if el.association:
parse_association_end(el, s)
@ -207,7 +236,7 @@ def parse_property(el, s):
parse_attribute(el, s)
@parse.when_type(UML.Operation)
@parse.when_type(Operation)
def parse_operation(el, s):
"""
Parse string s in the operation. Tagged values, parameters and
@ -217,28 +246,28 @@ def parse_operation(el, s):
if not m or m.group('garbage'):
el.name = s
del el.visibility
map(UML.Parameter.unlink, list(el.returnResult))
map(UML.Parameter.unlink, list(el.formalParameter))
list(map(Parameter.unlink, list(el.returnResult)))
list(map(Parameter.unlink, list(el.formalParameter)))
else:
g = m.group
create = el._factory.create
_set_visibility(el, g('vis'))
el.name = g('name')
if not el.returnResult:
el.returnResult = create(UML.Parameter)
el.returnResult = create(Parameter)
p = el.returnResult[0]
p.direction = 'return'
p.typeValue = g('type')
p.lowerValue = g('mult_l')
p.upperValue = g('mult_u')
# FIXME: Maybe add to Operation.ownedRule?
#tags = g('tags')
#if tags:
# tags = g('tags')
# if tags:
# for t in map(str.strip, tags.split(',')):
# tv = create(UML.LiteralSpecification)
# tv.value = t
# p.taggedValue = tv
pindex = 0
params = g('params')
while params:
@ -249,15 +278,15 @@ def parse_operation(el, s):
try:
p = el.formalParameter[pindex]
except IndexError:
p = create(UML.Parameter)
p = create(Parameter)
p.direction = g('dir') or 'in'
p.name = g('name')
p.typeValue = g('type')
p.lowerValue = g('mult_l')
p.upperValue = g('mult_u')
p.defaultValue = g('default')
#tags = g('tags')
#if tags:
# tags = g('tags')
# if tags:
# for t in map(str.strip, tags.split(',')):
# tv = create(UML.LiteralSpecification)
# tv.value = t
@ -272,6 +301,7 @@ def parse_operation(el, s):
for fp in el.formalParameter[pindex:]:
fp.unlink()
def parse_lifeline(el, s):
"""
Parse string s in a lifeline. If a class is defined and can be found
@ -289,9 +319,8 @@ def parse_lifeline(el, s):
t = g('type')
if t:
el.name += ': ' + t
# In the near future the data model should be extended with
# Lifeline.represents: ConnectableElement
# In the near future the data model should be extended with
# Lifeline.represents: ConnectableElement
def render_lifeline(el):
@ -300,12 +329,11 @@ def render_lifeline(el):
return el.name
@parse.when_type(UML.NamedElement)
@parse.when_type(NamedElement)
def parse_namedelement(el, text):
"""
Parse named element by simply assigning text to its name.
"""
el.name = text
# vim:sw=4:et:ai

View File

@ -1,16 +1,35 @@
#!/usr/bin/env python
"""This is Gaphor, a Python+GTK based UML modelling tool.
# Copyright (C) 2002-2017 Adam Boduch <adam.boduch@gmail.com>
# Arjan Molenaar <gaphor@gmail.com>
# Dan Yeaw <dan@yeaw.me>
#
# This file is part of Gaphor.
#
# Gaphor is free software: you can redistribute it and/or modify it under the
# terms of the GNU Library General Public License as published by the Free
# Software Foundation, either version 2 of the License, or (at your option)
# any later version.
#
# Gaphor is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
# more details.
#
# You should have received a copy of the GNU Library General Public
# along with Gaphor. If not, see <http://www.gnu.org/licenses/>.
"""
This module allows Gaphor to be launched from the command line.
The main() function sets up the command-line options and arguments and
passes them to the main Application instance."""
passes them to the main Application instance.
"""
__all__ = [ 'main' ]
from __future__ import absolute_import
from optparse import OptionParser
import logging
import pygtk
from optparse import OptionParser
import six.moves.builtins
from gaphor.application import Application
@ -18,6 +37,8 @@ pygtk.require('2.0')
LOG_FORMAT = '%(name)s %(levelname)s %(message)s'
__all__ = ['main']
def launch(model=None):
"""Start the main application by initiating and running Application.
@ -44,7 +65,8 @@ def launch(model=None):
file_manager.action_new()
Application.run()
def main():
"""Start Gaphor from the command line. This function creates an option
parser for retrieving arguments and options from the command line. This
@ -56,26 +78,19 @@ def main():
parser = OptionParser()
parser.add_option('-p',\
'--profiler',\
action='store_true',\
help='Run in profiler')
parser.add_option('-q', "--quiet",
dest='quiet', help='Quiet output',
default=False, action='store_true')
parser.add_option('-v', '--verbose',
dest='verbose', help='Verbose output',
default=False, action="store_true")
parser.add_option('-p', '--profiler', action='store_true', help='Run in profiler')
parser.add_option('-q', "--quiet", dest='quiet', help='Quiet output', default=False, action='store_true')
parser.add_option('-v', '--verbose', dest='verbose', help='Verbose output', default=False, action="store_true")
options, args = parser.parse_args()
if options.verbose:
logging.basicConfig(level=logging.DEBUG, format=LOG_FORMAT)
elif options.quiet:
logging.basicConfig(level=logging.WARNING, format=LOG_FORMAT)
else:
logging.basicConfig(level=logging.INFO, format=LOG_FORMAT)
try:
model = args[0]
except IndexError:
@ -86,19 +101,18 @@ def main():
import cProfile
import pstats
cProfile.run('import gaphor; gaphor.launch()',\
'gaphor.prof')
cProfile.run('import gaphor; gaphor.launch()', 'gaphor.prof')
profile_stats = pstats.Stats('gaphor.prof')
profile_stats.strip_dirs().sort_stats('time').print_stats(50)
else:
launch(model)
# TODO: Remove this.
import __builtin__
__builtin__.__dict__['log'] = logging.getLogger('Gaphor')
# TODO: Remove this.
six.moves.builtins.__dict__['log'] = logging.getLogger('Gaphor')
# vim:sw=4:et:ai

View File

@ -1,12 +1,31 @@
#!/usr/bin/env python
# Copyright (C) 2007-2017 Arjan Molenaar <gaphor@gmail.com>
# Dan Yeaw <dan@yeaw.me>
#
# This file is part of Gaphor.
#
# Gaphor is free software: you can redistribute it and/or modify it under the
# terms of the GNU Library General Public License as published by the Free
# Software Foundation, either version 2 of the License, or (at your option)
# any later version.
#
# Gaphor is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
# more details.
#
# You should have received a copy of the GNU Library General Public
# along with Gaphor. If not, see <http://www.gnu.org/licenses/>.
"""
Support for actions in generic files.
See also gaphor/service/actionmanager.py for the management module.
"""
from __future__ import absolute_import
from __future__ import absolute_import, print_function
from .application import Application
from gaphor.application import Application
class action(object):
@ -17,7 +36,7 @@ class action(object):
>>> class A(object):
... @action(name="my_action", label="my action")
... def myaction(self):
... print 'action called'
... print('action called')
>>> a = A()
>>> a.myaction()
action called
@ -25,7 +44,7 @@ class action(object):
True
>>> for method in dir(A):
... if is_action(getattr(A, method)):
... print method
... print(method)
myaction
>>> A.myaction.__action__.name
'my_action'
@ -44,13 +63,14 @@ class action(object):
def __call__(self, func):
func.__action__ = self
return func
class toggle_action(action):
"""
A toggle button can be switched on and off.
An extra 'active' attribute is provided than gives the initial status.
"""
def __init__(self, name, label=None, tooltip=None, stock_id=None, accel=None, active=False):
super(toggle_action, self).__init__(name, label, tooltip, stock_id, accel=accel, active=active)
@ -62,8 +82,10 @@ class radio_action(action):
The callback function should have an extra value property, which is
given the index number of the activated radio button action.
"""
def __init__(self, names, labels=None, tooltips=None, stock_ids=None, accels=None, active=0):
super(radio_action, self).__init__(names[0], names=names, labels=labels, tooltips=tooltips, stock_ids=stock_ids, accels=accels, active=active)
super(radio_action, self).__init__(names[0], names=names, labels=labels, tooltips=tooltips, stock_ids=stock_ids,
accels=accels, active=active)
def open_action(name, label=None, tooltip=None, stock_id=None, accel=None, **kwargs):
@ -73,7 +95,7 @@ def open_action(name, label=None, tooltip=None, stock_id=None, accel=None, **kwa
>>> class A(object):
... @open_action(name="my_action", label="my action")
... def myaction(self):
... print 'action called'
... print('action called')
>>> a = A()
>>> a.myaction()
action called
@ -81,7 +103,7 @@ def open_action(name, label=None, tooltip=None, stock_id=None, accel=None, **kwa
True
>>> for method in dir(A):
... if is_action(getattr(A, method)):
... print method
... print(method)
myaction
>>> A.myaction.__action__.name
'my_action'
@ -104,12 +126,12 @@ def build_action_group(obj, name=None):
>>> class A(object):
... @action(name='bar')
... def bar(self): print 'Say bar'
... def bar(self): print('Say bar')
... @toggle_action(name='foo')
... def foo(self, active): print 'Say foo', active
... def foo(self, active): print('Say foo', active)
... @radio_action(names=('baz', 'beer'), labels=('Baz', 'Beer'))
... def baz(self, value):
... print 'Say', value, (value and 'beer' or 'baz')
... print('Say', value, (value and "beer" or "baz"))
>>> group = build_action_group(A())
Say 0 baz
>>> len(group.list_actions())
@ -141,10 +163,14 @@ def build_action_group(obj, name=None):
act = getattr(method, '__action__', None)
if isinstance(act, radio_action):
actgroup = None
if not act.labels: act.labels = [None] * len(act.names)
if not act.tooltips: act.tooltips = [None] * len(act.names)
if not act.stock_ids: act.stock_ids = [None] * len(act.names)
if not act.accels: act.accels = [None] * len(act.names)
if not act.labels:
act.labels = [None] * len(act.names)
if not act.tooltips:
act.tooltips = [None] * len(act.names)
if not act.stock_ids:
act.stock_ids = [None] * len(act.names)
if not act.accels:
act.accels = [None] * len(act.names)
assert len(act.names) == len(act.labels)
assert len(act.names) == len(act.tooltips)
assert len(act.names) == len(act.stock_ids)
@ -173,12 +199,12 @@ def build_action_group(obj, name=None):
activate = act.opening and _action_opening or _action_activate
except AttributeError:
activate = _action_activate
gtkact.connect('activate', activate, obj, attrname)
group.add_action_with_accel(gtkact, act.accel)
elif act is not None:
raise TypeError, 'Invalid action type: %s' % action
raise TypeError('Invalid action type: %s' % action)
return group
@ -210,6 +236,7 @@ def _radio_action_changed(action, current_action, obj, name):
if __name__ == '__main__':
import doctest
doctest.testmod()
# vim:sw=4:et:ai

View File

@ -1,4 +1,24 @@
#!/usr/bin/env python
# Copyright (C) 2007-2017 Arjan Molenaar <gaphor@gmail.com>
# Artur Wroblewski <wrobell@pld-linux.org>
# Dan Yeaw <dan@yeaw.me>
#
# This file is part of Gaphor.
#
# Gaphor is free software: you can redistribute it and/or modify it under the
# terms of the GNU Library General Public License as published by the Free
# Software Foundation, either version 2 of the License, or (at your option)
# any later version.
#
# Gaphor is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
# more details.
#
# You should have received a copy of the GNU Library General Public
# along with Gaphor. If not, see <http://www.gnu.org/licenses/>.
from __future__ import absolute_import
import gaphor.adapters.connectors
import gaphor.adapters.editors

View File

@ -0,0 +1,18 @@
#!/usr/bin/env python
# Copyright (C) 2001-2009 Arjan Molenaar <gaphor@gmail.com>
#
# This file is part of Gaphor.
#
# Gaphor is free software: you can redistribute it and/or modify it under the
# terms of the GNU Library General Public License as published by the Free
# Software Foundation, either version 2 of the License, or (at your option)
# any later version.
#
# Gaphor is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
# more details.
#
# You should have received a copy of the GNU Library General Public
# along with Gaphor. If not, see <http://www.gnu.org/licenses/>.

View File

@ -1,10 +1,31 @@
#!/usr/bin/env python
# Copyright (C) 2009-2017 Arjan Molenaar <gaphor@gmail.com>
# Artur Wroblewski <wrobell@pld-linux.org>
# Dan Yeaw <dan@yeaw.me>
#
# This file is part of Gaphor.
#
# Gaphor is free software: you can redistribute it and/or modify it under the
# terms of the GNU Library General Public License as published by the Free
# Software Foundation, either version 2 of the License, or (at your option)
# any later version.
#
# Gaphor is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
# more details.
#
# You should have received a copy of the GNU Library General Public
# along with Gaphor. If not, see <http://www.gnu.org/licenses/>.
"""
Flow item adapter connections.
"""
from __future__ import absolute_import
from gaphor.adapters.connectors import UnaryRelationshipConnect, RelationshipConnect
from zope import interface, component
from gaphor import UML
from gaphor.UML import uml2
from gaphor.diagram import items
from gaphor.diagram.interfaces import IConnect
@ -18,8 +39,8 @@ class FlowConnect(UnaryRelationshipConnect):
line = self.line
subject = self.element.subject
if handle is line.head and isinstance(subject, UML.FinalNode) \
or handle is line.tail and isinstance(subject, UML.InitialNode):
if handle is line.head and isinstance(subject, uml2.FinalNode) \
or handle is line.tail and isinstance(subject, uml2.InitialNode):
return None
return super(FlowConnect, self).allow(handle, port)
@ -51,13 +72,13 @@ class FlowConnect(UnaryRelationshipConnect):
c1 = self.get_connected(line.head)
c2 = self.get_connected(line.tail)
if isinstance(c1, items.ObjectNodeItem) or isinstance(c2, items.ObjectNodeItem):
relation = self.relationship_or_new(UML.ObjectFlow,
UML.ObjectFlow.source,
UML.ObjectFlow.target)
relation = self.relationship_or_new(uml2.ObjectFlow,
uml2.ObjectFlow.source,
uml2.ObjectFlow.target)
else:
relation = self.relationship_or_new(UML.ControlFlow,
UML.ControlFlow.source,
UML.ControlFlow.target)
relation = self.relationship_or_new(uml2.ControlFlow,
uml2.ControlFlow.source,
uml2.ControlFlow.target)
line.subject = relation
opposite = line.opposite(handle)
otc = self.get_connected(opposite)
@ -125,10 +146,10 @@ class FlowForkDecisionNodeConnect(FlowConnect):
join_node = subject
# determine flow class:
if [ f for f in join_node.incoming if isinstance(f, UML.ObjectFlow) ]:
flow_class = UML.ObjectFlow
if [ f for f in join_node.incoming if isinstance(f, uml2.ObjectFlow) ]:
flow_class = uml2.ObjectFlow
else:
flow_class = UML.ControlFlow
flow_class = uml2.ControlFlow
self.element_factory.swap_element(join_node, join_node_cls)
fork_node = self.element_factory.create(fork_node_cls)
@ -194,8 +215,8 @@ class FlowForkNodeConnect(FlowForkDecisionNodeConnect):
"""
component.adapts(items.ForkNodeItem, items.FlowItem)
fork_node_cls=UML.ForkNode
join_node_cls=UML.JoinNode
fork_node_cls=uml2.ForkNode
join_node_cls=uml2.JoinNode
component.provideAdapter(FlowForkNodeConnect)
@ -206,8 +227,8 @@ class FlowDecisionNodeConnect(FlowForkDecisionNodeConnect):
"""
component.adapts(items.DecisionNodeItem, items.FlowItem)
fork_node_cls = UML.DecisionNode
join_node_cls = UML.MergeNode
fork_node_cls = uml2.DecisionNode
join_node_cls = uml2.MergeNode
component.provideAdapter(FlowDecisionNodeConnect)

View File

@ -1,12 +1,32 @@
#!/usr/bin/env python
# Copyright (C) 2009-2017 Arjan Molenaar <gaphor@gmail.com>
# Artur Wroblewski <wrobell@pld-linux.org>
# Dan Yeaw <dan@yeaw.me>
#
# This file is part of Gaphor.
#
# Gaphor is free software: you can redistribute it and/or modify it under the
# terms of the GNU Library General Public License as published by the Free
# Software Foundation, either version 2 of the License, or (at your option)
# any later version.
#
# Gaphor is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
# more details.
#
# You should have received a copy of the GNU Library General Public
# along with Gaphor. If not, see <http://www.gnu.org/licenses/>.
"""
Activity partition property page.
"""
from __future__ import absolute_import
import gtk
from gaphor.core import _, inject, transactional
from gaphor.ui.interfaces import IPropertyPage
from gaphor.diagram import items
from zope import interface, component
from gaphor import UML
from gaphor.adapters.propertypages import NamedItemPropertyPage

View File

@ -0,0 +1,18 @@
#!/usr/bin/env python
# Copyright (C) 2001-2009 Arjan Molenaar <gaphor@gmail.com>
#
# This file is part of Gaphor.
#
# Gaphor is free software: you can redistribute it and/or modify it under the
# terms of the GNU Library General Public License as published by the Free
# Software Foundation, either version 2 of the License, or (at your option)
# any later version.
#
# Gaphor is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
# more details.
#
# You should have received a copy of the GNU Library General Public
# along with Gaphor. If not, see <http://www.gnu.org/licenses/>.

View File

@ -1,9 +1,30 @@
#!/usr/bin/env python
# Copyright (C) 2009-2017 Arjan Molenaar <gaphor@gmail.com>
# Artur Wroblewski <wrobell@pld-linux.org>
# Dan Yeaw <dan@yeaw.me>
#
# This file is part of Gaphor.
#
# Gaphor is free software: you can redistribute it and/or modify it under the
# terms of the GNU Library General Public License as published by the Free
# Software Foundation, either version 2 of the License, or (at your option)
# any later version.
#
# Gaphor is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
# more details.
#
# You should have received a copy of the GNU Library General Public
# along with Gaphor. If not, see <http://www.gnu.org/licenses/>.
"""
Flow item connection adapters tests.
"""
from __future__ import absolute_import
from gaphor.tests import TestCase
from gaphor import UML
from gaphor.UML import uml2
from gaphor.diagram import items
class FlowItemBasicNodesConnectionTestCase(TestCase):
@ -14,7 +35,7 @@ class FlowItemBasicNodesConnectionTestCase(TestCase):
"""Test flow item glueing to initial node item
"""
flow = self.create(items.FlowItem)
node = self.create(items.InitialNodeItem, UML.InitialNode)
node = self.create(items.InitialNodeItem, uml2.InitialNode)
# tail may not connect to initial node item
allowed = self.allow(flow, flow.tail, node)
@ -28,7 +49,7 @@ class FlowItemBasicNodesConnectionTestCase(TestCase):
"""Test flow item glueing to flow final node item
"""
flow = self.create(items.FlowItem)
node = self.create(items.FlowFinalNodeItem, UML.FlowFinalNode)
node = self.create(items.FlowFinalNodeItem, uml2.FlowFinalNode)
# head may not connect to flow final node item
allowed = self.allow(flow, flow.head, node)
@ -42,7 +63,7 @@ class FlowItemBasicNodesConnectionTestCase(TestCase):
"""Test flow item glueing to activity final node item
"""
flow = self.create(items.FlowItem)
node = self.create(items.ActivityFinalNodeItem, UML.ActivityFinalNode)
node = self.create(items.ActivityFinalNodeItem, uml2.ActivityFinalNode)
# head may not connect to activity final node item
glued = self.allow(flow, flow.head, node)
@ -60,7 +81,7 @@ class FlowItemObjectNodeTestCase(TestCase):
"""Test glueing to object node
"""
flow = self.create(items.FlowItem)
onode = self.create(items.ObjectNodeItem, UML.ObjectNode)
onode = self.create(items.ObjectNodeItem, uml2.ObjectNode)
glued = self.allow(flow, flow.head, onode)
self.assertTrue(glued)
@ -69,13 +90,13 @@ class FlowItemObjectNodeTestCase(TestCase):
"""Test connection to object node
"""
flow = self.create(items.FlowItem)
anode = self.create(items.ActionItem, UML.Action)
onode = self.create(items.ObjectNodeItem, UML.ObjectNode)
anode = self.create(items.ActionItem, uml2.Action)
onode = self.create(items.ObjectNodeItem, uml2.ObjectNode)
self.connect(flow, flow.head, anode)
self.connect(flow, flow.tail, onode)
self.assertTrue(flow.subject)
self.assertTrue(isinstance(flow.subject, UML.ObjectFlow))
self.assertTrue(isinstance(flow.subject, uml2.ObjectFlow))
self.disconnect(flow, flow.head)
self.disconnect(flow, flow.tail)
@ -84,16 +105,16 @@ class FlowItemObjectNodeTestCase(TestCase):
self.connect(flow, flow.head, onode)
self.connect(flow, flow.tail, anode)
self.assertTrue(flow.subject)
self.assertTrue(isinstance(flow.subject, UML.ObjectFlow))
self.assertTrue(isinstance(flow.subject, uml2.ObjectFlow))
def test_reconnection(self):
"""Test object flow reconnection
"""
flow = self.create(items.FlowItem)
a1 = self.create(items.ActionItem, UML.Action)
o1 = self.create(items.ObjectNodeItem, UML.ObjectNode)
o2 = self.create(items.ObjectNodeItem, UML.ObjectNode)
a1 = self.create(items.ActionItem, uml2.Action)
o1 = self.create(items.ObjectNodeItem, uml2.ObjectNode)
o2 = self.create(items.ObjectNodeItem, uml2.ObjectNode)
# connect: a1 -> o1
self.connect(flow, flow.head, a1)
@ -115,7 +136,7 @@ class FlowItemObjectNodeTestCase(TestCase):
self.assertEquals(1, len(o2.subject.incoming))
self.assertEquals(0, len(o2.subject.outgoing))
self.assertEquals(1, len(self.kindof(UML.ObjectFlow)))
self.assertEquals(1, len(self.kindof(uml2.ObjectFlow)))
# one guard
self.assertEquals('tname', flow.subject.name)
self.assertEquals('tguard', flow.subject.guard)
@ -125,9 +146,9 @@ class FlowItemObjectNodeTestCase(TestCase):
"""Test control flow becoming object flow due to reconnection
"""
flow = self.create(items.FlowItem)
a1 = self.create(items.ActionItem, UML.Action)
a2 = self.create(items.ActionItem, UML.Action)
o1 = self.create(items.ObjectNodeItem, UML.ObjectNode)
a1 = self.create(items.ActionItem, uml2.Action)
a2 = self.create(items.ActionItem, uml2.Action)
o1 = self.create(items.ObjectNodeItem, uml2.ObjectNode)
# connect with control flow: a1 -> a2
self.connect(flow, flow.head, a1)
@ -149,8 +170,8 @@ class FlowItemObjectNodeTestCase(TestCase):
self.assertEquals(1, len(o1.subject.incoming))
self.assertEquals(0, len(o1.subject.outgoing))
self.assertEquals(0, len(self.kindof(UML.ControlFlow)))
self.assertEquals(1, len(self.kindof(UML.ObjectFlow)))
self.assertEquals(0, len(self.kindof(uml2.ControlFlow)))
self.assertEquals(1, len(self.kindof(uml2.ObjectFlow)))
# one guard, not changed
self.assertEquals('tname', flow.subject.name)
self.assertEquals('tguard', flow.subject.guard)
@ -165,8 +186,8 @@ class FlowItemActionTestCase(TestCase):
"""Test flow item glueing to action items
"""
flow = self.create(items.FlowItem)
a1 = self.create(items.ActionItem, UML.Action)
a2 = self.create(items.ActionItem, UML.Action)
a1 = self.create(items.ActionItem, uml2.Action)
a2 = self.create(items.ActionItem, uml2.Action)
glued = self.allow(flow, flow.head, a1)
self.assertTrue(glued)
@ -181,13 +202,13 @@ class FlowItemActionTestCase(TestCase):
"""Test flow item connecting to action items
"""
flow = self.create(items.FlowItem)
a1 = self.create(items.ActionItem, UML.Action)
a2 = self.create(items.ActionItem, UML.Action)
a1 = self.create(items.ActionItem, uml2.Action)
a2 = self.create(items.ActionItem, uml2.Action)
self.connect(flow, flow.head, a1)
self.connect(flow, flow.tail, a2)
self.assertTrue(isinstance(flow.subject, UML.ControlFlow))
self.assertTrue(isinstance(flow.subject, uml2.ControlFlow))
self.assertEquals(0, len(a1.subject.incoming))
self.assertEquals(1, len(a2.subject.incoming))
@ -204,8 +225,8 @@ class FlowItemActionTestCase(TestCase):
"""Test flow item disconnection from action items
"""
flow = self.create(items.FlowItem)
a1 = self.create(items.ActionItem, UML.Action)
a2 = self.create(items.ActionItem, UML.Action)
a1 = self.create(items.ActionItem, uml2.Action)
a2 = self.create(items.ActionItem, uml2.Action)
self.connect(flow, flow.head, a1)
self.connect(flow, flow.tail, a2)
@ -222,9 +243,9 @@ class FlowItemActionTestCase(TestCase):
"""Test flow item reconnection
"""
flow = self.create(items.FlowItem)
a1 = self.create(items.ActionItem, UML.Action)
a2 = self.create(items.ActionItem, UML.Action)
a3 = self.create(items.ActionItem, UML.Action)
a1 = self.create(items.ActionItem, uml2.Action)
a2 = self.create(items.ActionItem, uml2.Action)
a3 = self.create(items.ActionItem, uml2.Action)
# a1 -> a2
self.connect(flow, flow.head, a1)
@ -245,7 +266,7 @@ class FlowItemActionTestCase(TestCase):
self.assertEquals(1, len(a3.subject.incoming))
self.assertEquals(0, len(a3.subject.outgoing))
self.assertEquals(1, len(self.kindof(UML.ControlFlow)))
self.assertEquals(1, len(self.kindof(uml2.ControlFlow)))
# one guard
self.assertEquals('tname', flow.subject.name)
self.assertEquals('tguard', flow.subject.guard)
@ -255,9 +276,9 @@ class FlowItemActionTestCase(TestCase):
"""Test object flow becoming control flow due to reconnection
"""
flow = self.create(items.FlowItem)
a1 = self.create(items.ActionItem, UML.Action)
a2 = self.create(items.ActionItem, UML.Action)
o1 = self.create(items.ObjectNodeItem, UML.ObjectNode)
a1 = self.create(items.ActionItem, uml2.Action)
a2 = self.create(items.ActionItem, uml2.Action)
o1 = self.create(items.ObjectNodeItem, uml2.ObjectNode)
# connect with control flow: a1 -> o1
self.connect(flow, flow.head, a1)
@ -279,8 +300,8 @@ class FlowItemActionTestCase(TestCase):
self.assertEquals(1, len(a2.subject.incoming))
self.assertEquals(0, len(a2.subject.outgoing))
self.assertEquals(1, len(self.kindof(UML.ControlFlow)))
self.assertEquals(0, len(self.kindof(UML.ObjectFlow)))
self.assertEquals(1, len(self.kindof(uml2.ControlFlow)))
self.assertEquals(0, len(self.kindof(uml2.ObjectFlow)))
# one guard, not changed
self.assertEquals('tname', flow.subject.name)
self.assertEquals('tguard', flow.subject.guard)
@ -309,7 +330,7 @@ class FlowItemDesisionAndForkNodes:
"""Test decision/fork nodes glue
"""
flow = self.create(items.FlowItem)
action = self.create(items.ActionItem, UML.Action)
action = self.create(items.ActionItem, uml2.Action)
node = self.create(self.item_cls, self.join_node_cls)
glued = self.allow(flow, flow.head, node)
@ -336,9 +357,9 @@ class FlowItemDesisionAndForkNodes:
flow1 = self.create(items.FlowItem)
flow2 = self.create(items.FlowItem)
flow3 = self.create(items.FlowItem)
a1 = self.create(items.ActionItem, UML.Action)
a2 = self.create(items.ActionItem, UML.Action)
a3 = self.create(items.ActionItem, UML.Action)
a1 = self.create(items.ActionItem, uml2.Action)
a2 = self.create(items.ActionItem, uml2.Action)
a3 = self.create(items.ActionItem, uml2.Action)
jn = self.create(self.item_cls, self.fork_node_cls)
assert type(jn.subject) is self.fork_node_cls
@ -370,9 +391,9 @@ class FlowItemDesisionAndForkNodes:
flow1 = self.create(items.FlowItem)
flow2 = self.create(items.FlowItem)
flow3 = self.create(items.FlowItem)
a1 = self.create(items.ActionItem, UML.Action)
a2 = self.create(items.ActionItem, UML.Action)
a3 = self.create(items.ActionItem, UML.Action)
a1 = self.create(items.ActionItem, uml2.Action)
a2 = self.create(items.ActionItem, uml2.Action)
a3 = self.create(items.ActionItem, uml2.Action)
jn = self.create(self.item_cls, self.join_node_cls)
# connect actions first
@ -414,10 +435,10 @@ class FlowItemDesisionAndForkNodes:
flow2 = self.create(items.FlowItem)
flow3 = self.create(items.FlowItem)
flow4 = self.create(items.FlowItem)
a1 = self.create(items.ActionItem, UML.Action)
a2 = self.create(items.ActionItem, UML.Action)
a3 = self.create(items.ActionItem, UML.Action)
a4 = self.create(items.ActionItem, UML.Action)
a1 = self.create(items.ActionItem, uml2.Action)
a2 = self.create(items.ActionItem, uml2.Action)
a3 = self.create(items.ActionItem, uml2.Action)
a4 = self.create(items.ActionItem, uml2.Action)
jn = self.create(self.item_cls, self.join_node_cls)
# connect actions first
@ -458,10 +479,10 @@ class FlowItemDesisionAndForkNodes:
flow2 = self.create(items.FlowItem)
flow3 = self.create(items.FlowItem)
flow4 = self.create(items.FlowItem)
a1 = self.create(items.ActionItem, UML.Action)
a2 = self.create(items.ActionItem, UML.Action)
a3 = self.create(items.ActionItem, UML.Action)
a4 = self.create(items.ActionItem, UML.Action)
a1 = self.create(items.ActionItem, uml2.Action)
a2 = self.create(items.ActionItem, uml2.Action)
a3 = self.create(items.ActionItem, uml2.Action)
a4 = self.create(items.ActionItem, uml2.Action)
jn = self.create(self.item_cls, self.join_node_cls)
# connect actions first
@ -479,7 +500,7 @@ class FlowItemDesisionAndForkNodes:
# needed for tests below
cflow = jn.subject.outgoing[0]
cnode = jn.combined
assert cflow in self.kindof(UML.ControlFlow)
assert cflow in self.kindof(uml2.ControlFlow)
assert cnode in self.kindof(self.fork_node_cls)
# test disconnection
@ -487,7 +508,7 @@ class FlowItemDesisionAndForkNodes:
assert self.get_connected(flow4.head) is None
self.assertTrue(jn.combined is None)
flows = self.kindof(UML.ControlFlow)
flows = self.kindof(uml2.ControlFlow)
nodes = self.kindof(self.fork_node_cls)
self.assertTrue(cnode not in nodes, '%s in %s' % (cnode, nodes))
self.assertTrue(cflow not in flows, '%s in %s' % (cflow, flows))
@ -496,15 +517,15 @@ class FlowItemDesisionAndForkNodes:
class FlowItemForkNodeTestCase(FlowItemDesisionAndForkNodes, TestCase):
item_cls = items.ForkNodeItem
fork_node_cls = UML.ForkNode
join_node_cls = UML.JoinNode
fork_node_cls = uml2.ForkNode
join_node_cls = uml2.JoinNode
class FlowItemDecisionNodeTestCase(FlowItemDesisionAndForkNodes, TestCase):
item_cls = items.DecisionNodeItem
fork_node_cls = UML.DecisionNode
join_node_cls = UML.MergeNode
fork_node_cls = uml2.DecisionNode
join_node_cls = uml2.MergeNode

View File

@ -0,0 +1,18 @@
#!/usr/bin/env python
# Copyright (C) 2001-2009 Arjan Molenaar <gaphor@gmail.com>
#
# This file is part of Gaphor.
#
# Gaphor is free software: you can redistribute it and/or modify it under the
# terms of the GNU Library General Public License as published by the Free
# Software Foundation, either version 2 of the License, or (at your option)
# any later version.
#
# Gaphor is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
# more details.
#
# You should have received a copy of the GNU Library General Public
# along with Gaphor. If not, see <http://www.gnu.org/licenses/>.

View File

@ -1,12 +1,38 @@
#!/usr/bin/env python
# Copyright (C) 2009-2017 Arjan Molenaar <gaphor@gmail.com>
# Artur Wroblewski <wrobell@pld-linux.org>
# Dan Yeaw <dan@yeaw.me>
#
# This file is part of Gaphor.
#
# Gaphor is free software: you can redistribute it and/or modify it under the
# terms of the GNU Library General Public License as published by the Free
# Software Foundation, either version 2 of the License, or (at your option)
# any later version.
#
# Gaphor is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
# more details.
#
# You should have received a copy of the GNU Library General Public
# along with Gaphor. If not, see <http://www.gnu.org/licenses/>.
"""
Classes related (dependency, implementation) adapter connections.
"""
from __future__ import absolute_import
import logging
from zope import component
from gaphor.UML import uml2, modelfactory
from gaphor.adapters.connectors import UnaryRelationshipConnect, RelationshipConnect
from zope import interface, component
from gaphor import UML
from gaphor.diagram import items
log = logging.getLogger(__name__)
class DependencyConnect(RelationshipConnect):
"""
Connect two NamedItem elements using a Dependency
@ -19,12 +45,11 @@ class DependencyConnect(RelationshipConnect):
# Element should be a NamedElement
if not element.subject or \
not isinstance(element.subject, UML.NamedElement):
return False
not isinstance(element.subject, uml2.NamedElement):
return False
return super(DependencyConnect, self).allow(handle, port)
def reconnect(self, handle, port):
line = self.line
dep = line.subject
@ -36,7 +61,6 @@ class DependencyConnect(RelationshipConnect):
del dep.client[c]
self.reconnect_relationship(handle, line.dependency_type.supplier, line.dependency_type.client)
def connect_subject(self, handle):
"""
TODO: cleck for existing relationships (use self.relation())
@ -53,13 +77,14 @@ class DependencyConnect(RelationshipConnect):
else:
client = self.element.subject
supplier = self.get_connected(opposite).subject
line.dependency_type = UML.model.dependency_type(client, supplier)
line.dependency_type = modelfactory.dependency_type(client, supplier)
relation = self.relationship_or_new(line.dependency_type,
line.dependency_type.supplier,
line.dependency_type.client)
line.dependency_type.supplier,
line.dependency_type.client)
line.subject = relation
component.provideAdapter(DependencyConnect)
@ -70,21 +95,19 @@ class GeneralizationConnect(RelationshipConnect):
# FixMe: Both ends of the generalization should be of the same type?
component.adapts(items.ClassifierItem, items.GeneralizationItem)
def reconnect(self, handle, port):
self.reconnect_relationship(handle, UML.Generalization.general, UML.Generalization.specific)
self.reconnect_relationship(handle, uml2.Generalization.general, uml2.Generalization.specific)
def connect_subject(self, handle):
log.debug('connect_subject: ' % handle)
relation = self.relationship_or_new(UML.Generalization,
UML.Generalization.general,
UML.Generalization.specific)
log.debug('found: ' % relation)
log.debug('connect_subject: %s' % handle)
relation = self.relationship_or_new(uml2.Generalization,
uml2.Generalization.general,
uml2.Generalization.specific)
log.debug('found: %s' % relation)
self.line.subject = relation
component.provideAdapter(GeneralizationConnect)
component.provideAdapter(GeneralizationConnect)
class AssociationConnect(UnaryRelationshipConnect):
@ -97,7 +120,7 @@ class AssociationConnect(UnaryRelationshipConnect):
element = self.element
# Element should be a Classifier
if not isinstance(element.subject, UML.Classifier):
if not isinstance(element.subject, uml2.Classifier):
return None
return super(AssociationConnect, self).allow(handle, port)
@ -117,11 +140,11 @@ class AssociationConnect(UnaryRelationshipConnect):
end1 = line.subject.memberEnd[0]
end2 = line.subject.memberEnd[1]
if (end1.type is head_type and end2.type is tail_type) \
or (end2.type is head_type and end1.type is tail_type):
or (end2.type is head_type and end1.type is tail_type):
return
# Create new association
relation = UML.model.create_association(self.element_factory, head_type, tail_type)
relation = modelfactory.create_association(self.element_factory, head_type, tail_type)
relation.package = element.canvas.diagram.namespace
line.head_end.subject = relation.memberEnd[0]
@ -144,11 +167,10 @@ class AssociationConnect(UnaryRelationshipConnect):
nav = oend.subject.navigability
UML.model.set_navigability(line.subject, end.subject, None) # clear old data
modelfactory.set_navigability(line.subject, end.subject, None) # clear old data
oend.subject.type = c.subject
UML.model.set_navigability(line.subject, oend.subject, nav)
modelfactory.set_navigability(line.subject, oend.subject, nav)
def disconnect_subject(self, handle):
"""
@ -173,31 +195,28 @@ class AssociationConnect(UnaryRelationshipConnect):
component.provideAdapter(AssociationConnect)
class ImplementationConnect(RelationshipConnect):
"""
Connect Interface and a BehavioredClassifier using an Implementation.
"""
component.adapts(items.NamedItem, items.ImplementationItem)
def allow(self, handle, port):
line = self.line
element = self.element
# Element at the head should be an Interface
if handle is line.head and \
not isinstance(element.subject, UML.Interface):
not isinstance(element.subject, uml2.Interface):
return None
# Element at the tail should be a BehavioredClassifier
if handle is line.tail and \
not isinstance(element.subject, UML.BehavioredClassifier):
not isinstance(element.subject, uml2.BehavioredClassifier):
return None
return super(ImplementationConnect, self).allow(handle, port)
def reconnect(self, handle, port):
line = self.line
impl = line.subject
@ -207,16 +226,15 @@ class ImplementationConnect(RelationshipConnect):
elif handle is line.tail:
for c in impl.implementatingClassifier:
del impl.implementatingClassifier[c]
self.reconnect_relationship(handle, UML.Implementation.contract, UML.Implementation.implementatingClassifier)
self.reconnect_relationship(handle, uml2.Implementation.contract, uml2.Implementation.implementatingClassifier)
def connect_subject(self, handle):
"""
Perform implementation relationship connection.
"""
relation = self.relationship_or_new(UML.Implementation,
UML.Implementation.contract,
UML.Implementation.implementatingClassifier)
relation = self.relationship_or_new(uml2.Implementation,
uml2.Implementation.contract,
uml2.Implementation.implementatingClassifier)
self.line.subject = relation

View File

@ -1,3 +1,23 @@
#!/usr/bin/env python
# Copyright (C) 2009-2017 Arjan Molenaar <gaphor@gmail.com>
# Artur Wroblewski <wrobell@pld-linux.org>
# Dan Yeaw <dan@yeaw.me>
#
# This file is part of Gaphor.
#
# Gaphor is free software: you can redistribute it and/or modify it under the
# terms of the GNU Library General Public License as published by the Free
# Software Foundation, either version 2 of the License, or (at your option)
# any later version.
#
# Gaphor is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
# more details.
#
# You should have received a copy of the GNU Library General Public
# along with Gaphor. If not, see <http://www.gnu.org/licenses/>.
"""
Interface item related connections.
@ -6,9 +26,8 @@ to folded interface, see `gaphor.diagram.classes.interface` documentation
for details.
"""
from __future__ import absolute_import
from zope import interface, component
from gaphor import UML
from gaphor.diagram import items
from gaphor.adapters.classes.classconnect import DependencyConnect, ImplementationConnect

View File

@ -0,0 +1,18 @@
#!/usr/bin/env python
# Copyright (C) 2001-2009 Arjan Molenaar <gaphor@gmail.com>
#
# This file is part of Gaphor.
#
# Gaphor is free software: you can redistribute it and/or modify it under the
# terms of the GNU Library General Public License as published by the Free
# Software Foundation, either version 2 of the License, or (at your option)
# any later version.
#
# Gaphor is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
# more details.
#
# You should have received a copy of the GNU Library General Public
# along with Gaphor. If not, see <http://www.gnu.org/licenses/>.

View File

@ -1,20 +1,44 @@
#!/usr/bin/env python
# Copyright (C) 2009-2017 Arjan Molenaar <gaphor@gmail.com>
# Artur Wroblewski <wrobell@pld-linux.org>
# Dan Yeaw <dan@yeaw.me>
#
# This file is part of Gaphor.
#
# Gaphor is free software: you can redistribute it and/or modify it under the
# terms of the GNU Library General Public License as published by the Free
# Software Foundation, either version 2 of the License, or (at your option)
# any later version.
#
# Gaphor is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
# more details.
#
# You should have received a copy of the GNU Library General Public
# along with Gaphor. If not, see <http://www.gnu.org/licenses/>.
"""
Classes related adapter connection tests.
"""
from gaphor.tests import TestCase
from gaphor import UML
from __future__ import absolute_import
from gaphor.UML import uml2, modelfactory
from gaphor.diagram import items
from gaphor.tests import TestCase
class DependencyTestCase(TestCase):
"""
Dependency item connection adapter tests.
"""
def test_dependency_glue(self):
"""Test dependency glue to two actor items
"""
actor1 = self.create(items.ActorItem, UML.Actor)
actor2 = self.create(items.ActorItem, UML.Actor)
actor1 = self.create(items.ActorItem, uml2.Actor)
actor2 = self.create(items.ActorItem, uml2.Actor)
dep = self.create(items.DependencyItem)
glued = self.allow(dep, dep.head, actor1)
@ -25,19 +49,18 @@ class DependencyTestCase(TestCase):
glued = self.allow(dep, dep.tail, actor2)
self.assertTrue(glued)
def test_dependency_connect(self):
"""Test dependency connecting to two actor items
"""
actor1 = self.create(items.ActorItem, UML.Actor)
actor2 = self.create(items.ActorItem, UML.Actor)
actor1 = self.create(items.ActorItem, uml2.Actor)
actor2 = self.create(items.ActorItem, uml2.Actor)
dep = self.create(items.DependencyItem)
self.connect(dep, dep.head, actor1)
self.connect(dep, dep.tail, actor2)
self.assertTrue(dep.subject is not None)
self.assertTrue(isinstance(dep.subject, UML.Dependency))
self.assertTrue(isinstance(dep.subject, uml2.Dependency))
self.assertTrue(dep.subject in self.element_factory.select())
hct = self.get_connected(dep.head)
@ -48,13 +71,12 @@ class DependencyTestCase(TestCase):
self.assertTrue(actor1.subject in dep.subject.supplier)
self.assertTrue(actor2.subject in dep.subject.client)
def test_dependency_reconnection(self):
"""Test dependency reconnection
"""
a1 = self.create(items.ActorItem, UML.Actor)
a2 = self.create(items.ActorItem, UML.Actor)
a3 = self.create(items.ActorItem, UML.Actor)
a1 = self.create(items.ActorItem, uml2.Actor)
a2 = self.create(items.ActorItem, uml2.Actor)
a3 = self.create(items.ActorItem, uml2.Actor)
dep = self.create(items.DependencyItem)
# connect: a1 -> a2
@ -73,12 +95,11 @@ class DependencyTestCase(TestCase):
self.assertTrue(a3.subject in dep.subject.client)
self.assertTrue(a2.subject not in dep.subject.client, dep.subject.client)
def test_dependency_disconnect(self):
"""Test dependency disconnecting using two actor items
"""
actor1 = self.create(items.ActorItem, UML.Actor)
actor2 = self.create(items.ActorItem, UML.Actor)
actor1 = self.create(items.ActorItem, uml2.Actor)
actor2 = self.create(items.ActorItem, uml2.Actor)
dep = self.create(items.DependencyItem)
self.connect(dep, dep.head, actor1)
@ -93,12 +114,11 @@ class DependencyTestCase(TestCase):
self.assertTrue(dep_subj not in actor1.subject.supplierDependency)
self.assertTrue(dep_subj not in actor2.subject.clientDependency)
def test_dependency_reconnect(self):
"""Test dependency reconnection using two actor items
"""
actor1 = self.create(items.ActorItem, UML.Actor)
actor2 = self.create(items.ActorItem, UML.Actor)
actor1 = self.create(items.ActorItem, uml2.Actor)
actor2 = self.create(items.ActorItem, uml2.Actor)
dep = self.create(items.DependencyItem)
self.connect(dep, dep.head, actor1)
@ -111,25 +131,24 @@ class DependencyTestCase(TestCase):
self.connect(dep, dep.tail, actor2)
self.assertTrue(dep.subject is not None)
self.assertTrue(dep.subject is not dep_subj) # the old subject has been deleted
self.assertTrue(dep.subject is not dep_subj) # the old subject has been deleted
self.assertTrue(dep.subject in actor1.subject.supplierDependency)
self.assertTrue(dep.subject in actor2.subject.clientDependency)
# TODO: test with interface (usage) and component (realization)
# TODO: test with multiple diagrams (should reuse existing relationships first)
def test_multi_dependency(self):
"""Test multiple dependencies
Dependency should appear in a new diagram, bound on a new
dependency item.
"""
actoritem1 = self.create(items.ActorItem, UML.Actor)
actoritem2 = self.create(items.ActorItem, UML.Actor)
actoritem1 = self.create(items.ActorItem, uml2.Actor)
actoritem2 = self.create(items.ActorItem, uml2.Actor)
actor1 = actoritem1.subject
actor2 = actoritem2.subject
dep = self.create(items.DependencyItem)
self.connect(dep, dep.head, actoritem1)
self.connect(dep, dep.tail, actoritem2)
@ -141,7 +160,7 @@ class DependencyTestCase(TestCase):
# Do the same thing, but now on a new diagram:
diagram2 = self.element_factory.create(UML.Diagram)
diagram2 = self.element_factory.create(uml2.Diagram)
actoritem3 = diagram2.create(items.ActorItem, subject=actor1)
actoritem4 = diagram2.create(items.ActorItem, subject=actor2)
dep2 = diagram2.create(items.DependencyItem)
@ -159,21 +178,20 @@ class DependencyTestCase(TestCase):
self.assertSame(dep.subject, dep2.subject)
def test_dependency_type_auto(self):
"""Test dependency type automatic determination
"""
cls = self.create(items.ClassItem, UML.Class)
iface = self.create(items.InterfaceItem, UML.Interface)
cls = self.create(items.ClassItem, uml2.Class)
iface = self.create(items.InterfaceItem, uml2.Interface)
dep = self.create(items.DependencyItem)
assert dep.auto_dependency
self.connect(dep, dep.tail, cls) # connect client
self.connect(dep, dep.head, iface) # connect supplier
self.connect(dep, dep.tail, cls) # connect client
self.connect(dep, dep.head, iface) # connect supplier
self.assertTrue(dep.subject is not None)
self.assertTrue(isinstance(dep.subject, UML.Usage), dep.subject)
self.assertTrue(isinstance(dep.subject, uml2.Usage), dep.subject)
self.assertTrue(dep.subject in self.element_factory.select())
@ -181,12 +199,13 @@ class GeneralizationTestCase(TestCase):
"""
Generalization item connection adapter tests.
"""
def test_glue(self):
"""Test generalization item glueing using two classes
"""
gen = self.create(items.GeneralizationItem)
c1 = self.create(items.ClassItem, UML.Class)
c2 = self.create(items.ClassItem, UML.Class)
c1 = self.create(items.ClassItem, uml2.Class)
c2 = self.create(items.ClassItem, uml2.Class)
glued = self.allow(gen, gen.tail, c1)
self.assertTrue(glued)
@ -198,13 +217,12 @@ class GeneralizationTestCase(TestCase):
glued = self.allow(gen, gen.head, c2)
self.assertTrue(glued)
def test_connection(self):
"""Test generalization item connection using two classes
"""
gen = self.create(items.GeneralizationItem)
c1 = self.create(items.ClassItem, UML.Class)
c2 = self.create(items.ClassItem, UML.Class)
c1 = self.create(items.ClassItem, uml2.Class)
c2 = self.create(items.ClassItem, uml2.Class)
self.connect(gen, gen.tail, c1)
assert self.get_connected(gen.tail) is c1
@ -220,8 +238,8 @@ class GeneralizationTestCase(TestCase):
On reconnection a new Generalization is created.
"""
gen = self.create(items.GeneralizationItem)
c1 = self.create(items.ClassItem, UML.Class)
c2 = self.create(items.ClassItem, UML.Class)
c1 = self.create(items.ClassItem, uml2.Class)
c2 = self.create(items.ClassItem, uml2.Class)
self.connect(gen, gen.tail, c1)
assert self.get_connected(gen.tail) is c1
@ -232,7 +250,7 @@ class GeneralizationTestCase(TestCase):
self.assertTrue(gen.subject.specific is c1.subject)
# Now do the same on a new diagram:
diagram2 = self.element_factory.create(UML.Diagram)
diagram2 = self.element_factory.create(uml2.Diagram)
c3 = diagram2.create(items.ClassItem, subject=c1.subject)
c4 = diagram2.create(items.ClassItem, subject=c2.subject)
gen2 = diagram2.create(items.GeneralizationItem)
@ -246,16 +264,15 @@ class GeneralizationTestCase(TestCase):
self.assertNotSame(gen.subject, gen2.subject)
self.assertEquals(1, len(c1.subject.generalization))
self.assertSame(c1.subject.generalization[0], gen.subject)
#self.assertEquals(1, len(actor2.clientDependency))
#self.assertTrue(actor2.clientDependency[0] is dep.subject)
# self.assertEquals(1, len(actor2.clientDependency))
# self.assertTrue(actor2.clientDependency[0] is dep.subject)
def test_reconnection2(self):
"""Test reconnection of generalization
"""
c1 = self.create(items.ClassItem, UML.Class)
c2 = self.create(items.ClassItem, UML.Class)
c3 = self.create(items.ClassItem, UML.Class)
c1 = self.create(items.ClassItem, uml2.Class)
c2 = self.create(items.ClassItem, uml2.Class)
c3 = self.create(items.ClassItem, uml2.Class)
gen = self.create(items.GeneralizationItem)
# connect: c1 -> c2
@ -277,12 +294,13 @@ class AssociationConnectorTestCase(TestCase):
"""
Association item connection adapters tests.
"""
def test_glue(self):
"""Test association item glue
"""
asc = self.create(items.AssociationItem)
c1 = self.create(items.ClassItem, UML.Class)
c2 = self.create(items.ClassItem, UML.Class)
c1 = self.create(items.ClassItem, uml2.Class)
c2 = self.create(items.ClassItem, uml2.Class)
glued = self.allow(asc, asc.head, c1)
self.assertTrue(glued)
@ -292,37 +310,35 @@ class AssociationConnectorTestCase(TestCase):
glued = self.allow(asc, asc.tail, c2)
self.assertTrue(glued)
def test_connect(self):
"""Test association item connection
"""
asc = self.create(items.AssociationItem)
c1 = self.create(items.ClassItem, UML.Class)
c2 = self.create(items.ClassItem, UML.Class)
c1 = self.create(items.ClassItem, uml2.Class)
c2 = self.create(items.ClassItem, uml2.Class)
self.connect(asc, asc.head, c1)
self.assertTrue(asc.subject is None) # no UML metaclass yet
self.assertTrue(asc.subject is None) # no UML metaclass yet
self.connect(asc, asc.tail, c2)
self.assertTrue(asc.subject is not None)
# Diagram, Class *2, Property *2, Association
self.assertEquals(6, len(list(self.element_factory.select())))
self.assertTrue(asc.head_end.subject is not None)
self.assertTrue(asc.tail_end.subject is not None)
def test_reconnect(self):
"""Test association item reconnection
"""
asc = self.create(items.AssociationItem)
c1 = self.create(items.ClassItem, UML.Class)
c2 = self.create(items.ClassItem, UML.Class)
c3 = self.create(items.ClassItem, UML.Class)
c1 = self.create(items.ClassItem, uml2.Class)
c2 = self.create(items.ClassItem, uml2.Class)
c3 = self.create(items.ClassItem, uml2.Class)
self.connect(asc, asc.head, c1)
self.connect(asc, asc.tail, c2)
UML.model.set_navigability(asc.subject, asc.tail_end.subject, True)
modelfactory.set_navigability(asc.subject, asc.tail_end.subject, True)
a = asc.subject
@ -335,24 +351,22 @@ class AssociationConnectorTestCase(TestCase):
self.assertTrue(c2.subject not in ends)
self.assertTrue(asc.tail_end.subject.navigability)
def test_disconnect(self):
"""Test association item disconnection
"""
asc = self.create(items.AssociationItem)
c1 = self.create(items.ClassItem, UML.Class)
c2 = self.create(items.ClassItem, UML.Class)
c1 = self.create(items.ClassItem, uml2.Class)
c2 = self.create(items.ClassItem, uml2.Class)
self.connect(asc, asc.head, c1)
self.assertTrue(asc.subject is None) # no UML metaclass yet
self.assertTrue(asc.subject is None) # no UML metaclass yet
self.connect(asc, asc.tail, c2)
assert asc.subject is not None
self.disconnect(asc, asc.head)
# after disconnection: one diagram and two classes
self.assertEquals(3, len(list(self.element_factory.select())))
# vim:sw=4:et:ai

View File

@ -1,8 +1,29 @@
#!/usr/bin/env python
# Copyright (C) 2009-2017 Arjan Molenaar <gaphor@gmail.com>
# Artur Wroblewski <wrobell@pld-linux.org>
# Dan Yeaw <dan@yeaw.me>
#
# This file is part of Gaphor.
#
# Gaphor is free software: you can redistribute it and/or modify it under the
# terms of the GNU Library General Public License as published by the Free
# Software Foundation, either version 2 of the License, or (at your option)
# any later version.
#
# Gaphor is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
# more details.
#
# You should have received a copy of the GNU Library General Public
# along with Gaphor. If not, see <http://www.gnu.org/licenses/>.
"""
Test implementation (interface realization) item connectors.
"""
from gaphor import UML
from __future__ import absolute_import
from gaphor.UML import uml2
from gaphor.diagram import items
from gaphor.tests import TestCase
@ -11,7 +32,7 @@ class ImplementationTestCase(TestCase):
"""Test non-interface glueing with implementation
"""
impl = self.create(items.ImplementationItem)
clazz = self.create(items.ClassItem, UML.Class)
clazz = self.create(items.ClassItem, uml2.Class)
glued = self.allow(impl, impl.head, clazz)
# connecting head to non-interface item is disallowed
@ -21,7 +42,7 @@ class ImplementationTestCase(TestCase):
def test_interface_glue(self):
"""Test interface glueing with implementation
"""
iface = self.create(items.InterfaceItem, UML.Interface)
iface = self.create(items.InterfaceItem, uml2.Interface)
impl = self.create(items.ImplementationItem)
glued = self.allow(impl, impl.head, iface)
@ -32,7 +53,7 @@ class ImplementationTestCase(TestCase):
"""Test classifier glueing with implementation
"""
impl = self.create(items.ImplementationItem)
clazz = self.create(items.ClassItem, UML.Class)
clazz = self.create(items.ClassItem, uml2.Class)
glued = self.allow(impl, impl.tail, clazz)
self.assertTrue(glued)
@ -41,15 +62,15 @@ class ImplementationTestCase(TestCase):
def test_connection(self):
"""Test connection of class and interface with implementation
"""
iface = self.create(items.InterfaceItem, UML.Interface)
iface = self.create(items.InterfaceItem, uml2.Interface)
impl = self.create(items.ImplementationItem)
clazz = self.create(items.ClassItem, UML.Class)
clazz = self.create(items.ClassItem, uml2.Class)
self.connect(impl, impl.head, iface)
self.connect(impl, impl.tail, clazz)
# check the datamodel
self.assertTrue(isinstance(impl.subject, UML.Implementation))
self.assertTrue(isinstance(impl.subject, uml2.Implementation))
ct = self.get_connected(impl.head)
self.assertTrue(ct is iface)
self.assertTrue(impl.subject is not None)
@ -60,9 +81,9 @@ class ImplementationTestCase(TestCase):
def test_reconnection(self):
"""Test reconnection of class and interface with implementation
"""
iface = self.create(items.InterfaceItem, UML.Interface)
c1 = self.create(items.ClassItem, UML.Class)
c2 = self.create(items.ClassItem, UML.Class)
iface = self.create(items.InterfaceItem, uml2.Interface)
c1 = self.create(items.ClassItem, uml2.Class)
c2 = self.create(items.ClassItem, uml2.Class)
impl = self.create(items.ImplementationItem)
# connect: iface -> c1

View File

@ -1,8 +1,28 @@
#!/usr/bin/env python
# Copyright (C) 2009-2017 Arjan Molenaar <gaphor@gmail.com>
# Dan Yeaw <dan@yeaw.me>
#
# This file is part of Gaphor.
#
# Gaphor is free software: you can redistribute it and/or modify it under the
# terms of the GNU Library General Public License as published by the Free
# Software Foundation, either version 2 of the License, or (at your option)
# any later version.
#
# Gaphor is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
# more details.
#
# You should have received a copy of the GNU Library General Public
# along with Gaphor. If not, see <http://www.gnu.org/licenses/>.
"""
Test connections to folded interface.
"""
from gaphor import UML
from __future__ import absolute_import
from gaphor.UML import uml2
from gaphor.diagram import items
from gaphor.tests import TestCase
@ -10,7 +30,7 @@ class ImplementationTestCase(TestCase):
def test_folded_interface_connection(self):
"""Test connecting implementation to folded interface
"""
iface = self.create(items.InterfaceItem, UML.Interface)
iface = self.create(items.InterfaceItem, uml2.Interface)
iface.folded = iface.FOLDED_PROVIDED
impl = self.create(items.ImplementationItem)
@ -22,7 +42,7 @@ class ImplementationTestCase(TestCase):
def test_folded_interface_disconnection(self):
"""Test disconnection implementation from folded interface
"""
iface = self.create(items.InterfaceItem, UML.Interface)
iface = self.create(items.InterfaceItem, uml2.Interface)
iface.folded = iface.FOLDED_PROVIDED
impl = self.create(items.ImplementationItem)
@ -38,7 +58,7 @@ class DependencyTestCase(TestCase):
def test_folded_interface_connection(self):
"""Test connecting dependency to folded interface
"""
iface = self.create(items.InterfaceItem, UML.Interface)
iface = self.create(items.InterfaceItem, uml2.Interface)
iface.folded = iface.FOLDED_PROVIDED
dep = self.create(items.DependencyItem)
@ -52,7 +72,7 @@ class DependencyTestCase(TestCase):
def test_folded_interface_disconnection(self):
"""Test disconnection dependency from folded interface
"""
iface = self.create(items.InterfaceItem, UML.Interface)
iface = self.create(items.InterfaceItem, uml2.Interface)
iface.folded = iface.FOLDED_PROVIDED
dep = self.create(items.DependencyItem)
@ -69,7 +89,7 @@ class DependencyTestCase(TestCase):
def test_unfolded_interface_disconnection(self):
"""Test disconnection dependency from unfolded interface
"""
iface = self.create(items.InterfaceItem, UML.Interface)
iface = self.create(items.InterfaceItem, uml2.Interface)
dep = self.create(items.DependencyItem)
self.connect(dep, dep.head, iface, iface.ports()[0])
@ -96,7 +116,7 @@ class FoldedInterfaceMultipleLinesTestCase(TestCase):
def setUp(self):
super(FoldedInterfaceMultipleLinesTestCase, self).setUp()
self.iface = self.create(items.InterfaceItem, UML.Interface)
self.iface = self.create(items.InterfaceItem, uml2.Interface)
self.iface.folded = self.iface.FOLDED_PROVIDED
@ -135,7 +155,7 @@ class FoldedInterfaceSingleLineTestCase(TestCase):
def test_interface_with_forbidden_lines(self):
"""Test glueing forbidden lines to folded interface
"""
iface = self.create(items.InterfaceItem, UML.Interface)
iface = self.create(items.InterfaceItem, uml2.Interface)
iface.folded = iface.FOLDED_PROVIDED
for cls in LINES[2:]:

View File

@ -0,0 +1,18 @@
#!/usr/bin/env python
# Copyright (C) 2001-2009 Arjan Molenaar <gaphor@gmail.com>
#
# This file is part of Gaphor.
#
# Gaphor is free software: you can redistribute it and/or modify it under the
# terms of the GNU Library General Public License as published by the Free
# Software Foundation, either version 2 of the License, or (at your option)
# any later version.
#
# Gaphor is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
# more details.
#
# You should have received a copy of the GNU Library General Public
# along with Gaphor. If not, see <http://www.gnu.org/licenses/>.

View File

@ -1,3 +1,23 @@
#!/usr/bin/env python
# Copyright (C) 2009-2017 Arjan Molenaar <gaphor@gmail.com>
# Artur Wroblewski <wrobell@pld-linux.org>
# Dan Yeaw <dan@yeaw.me>
#
# This file is part of Gaphor.
#
# Gaphor is free software: you can redistribute it and/or modify it under the
# terms of the GNU Library General Public License as published by the Free
# Software Foundation, either version 2 of the License, or (at your option)
# any later version.
#
# Gaphor is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
# more details.
#
# You should have received a copy of the GNU Library General Public
# along with Gaphor. If not, see <http://www.gnu.org/licenses/>.
"""
Connector connections.
@ -5,9 +25,9 @@ Implemented using interface item in assembly connector mode, see
`gaphor.diagram.connector` module for details.
"""
from __future__ import absolute_import
from zope import component
from gaphor import UML
from gaphor.UML import uml2
from gaphor.diagram import items
from gaphor.adapters.connectors import AbstractConnect
@ -82,9 +102,9 @@ class ConnectorConnectBase(AbstractConnect):
"""
connector.subject = assembly
end = self.element_factory.create(UML.ConnectorEnd)
end = self.element_factory.create(uml2.ConnectorEnd)
end.role = iface
end.partWithPort = self.element_factory.create(UML.Port)
end.partWithPort = self.element_factory.create(uml2.Port)
assembly.end = end
component.subject.ownedPort = end.partWithPort
@ -168,7 +188,7 @@ class ConnectorConnectBase(AbstractConnect):
break
if assembly is None:
assembly = self.element_factory.create(UML.Connector)
assembly = self.element_factory.create(uml2.Connector)
assembly.kind = 'assembly'
for c in connections:
connector = c.item

View File

@ -0,0 +1,18 @@
#!/usr/bin/env python
# Copyright (C) 2001-2009 Arjan Molenaar <gaphor@gmail.com>
#
# This file is part of Gaphor.
#
# Gaphor is free software: you can redistribute it and/or modify it under the
# terms of the GNU Library General Public License as published by the Free
# Software Foundation, either version 2 of the License, or (at your option)
# any later version.
#
# Gaphor is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
# more details.
#
# You should have received a copy of the GNU Library General Public
# along with Gaphor. If not, see <http://www.gnu.org/licenses/>.

View File

@ -1,9 +1,30 @@
#!/usr/bin/env python
# Copyright (C) 2009-2017 Arjan Molenaar <gaphor@gmail.com>
# Artur Wroblewski <wrobell@pld-linux.org>
# Dan Yeaw <dan@yeaw.me>
#
# This file is part of Gaphor.
#
# Gaphor is free software: you can redistribute it and/or modify it under the
# terms of the GNU Library General Public License as published by the Free
# Software Foundation, either version 2 of the License, or (at your option)
# any later version.
#
# Gaphor is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
# more details.
#
# You should have received a copy of the GNU Library General Public
# along with Gaphor. If not, see <http://www.gnu.org/licenses/>.
"""
Test connector item connectors.
"""
from __future__ import absolute_import
from gaphor.tests import TestCase
from gaphor import UML
from gaphor.UML import uml2
from gaphor.diagram import items
from gaphor.adapters.components.connectorconnect import ConnectorConnectBase
@ -15,7 +36,7 @@ class ComponentConnectTestCase(TestCase):
def test_glue(self):
"""Test glueing connector to component
"""
component = self.create(items.ComponentItem, UML.Component)
component = self.create(items.ComponentItem, uml2.Component)
line = self.create(items.ConnectorItem)
glued = self.allow(line, line.head, component)
@ -25,7 +46,7 @@ class ComponentConnectTestCase(TestCase):
def test_connection(self):
"""Test connecting connector to a component
"""
component = self.create(items.ComponentItem, UML.Component)
component = self.create(items.ComponentItem, uml2.Component)
line = self.create(items.ConnectorItem)
self.connect(line, line.head, component)
@ -36,8 +57,8 @@ class ComponentConnectTestCase(TestCase):
def test_glue_both(self):
"""Test glueing connector to component when one is connected
"""
c1 = self.create(items.ComponentItem, UML.Component)
c2 = self.create(items.ComponentItem, UML.Component)
c1 = self.create(items.ComponentItem, uml2.Component)
c2 = self.create(items.ComponentItem, uml2.Component)
line = self.create(items.ConnectorItem)
self.connect(line, line.head, c1)
@ -53,7 +74,7 @@ class InterfaceConnectTestCase(TestCase):
def test_non_folded_glue(self):
"""Test non-folded interface glueing
"""
iface = self.create(items.InterfaceItem, UML.Component)
iface = self.create(items.InterfaceItem, uml2.Component)
line = self.create(items.ConnectorItem)
glued = self.allow(line, line.head, iface)
@ -63,7 +84,7 @@ class InterfaceConnectTestCase(TestCase):
def test_folded_glue(self):
"""Test folded interface glueing
"""
iface = self.create(items.InterfaceItem, UML.Component)
iface = self.create(items.InterfaceItem, uml2.Component)
line = self.create(items.ConnectorItem)
iface.folded = iface.FOLDED_REQUIRED
@ -74,7 +95,7 @@ class InterfaceConnectTestCase(TestCase):
def test_glue_when_dependency_connected(self):
"""Test interface glueing, when dependency connected
"""
iface = self.create(items.InterfaceItem, UML.Component)
iface = self.create(items.InterfaceItem, uml2.Component)
dep = self.create(items.DependencyItem)
line = self.create(items.ConnectorItem)
@ -88,7 +109,7 @@ class InterfaceConnectTestCase(TestCase):
def test_glue_when_implementation_connected(self):
"""Test interface glueing, when implementation connected
"""
iface = self.create(items.InterfaceItem, UML.Component)
iface = self.create(items.InterfaceItem, uml2.Component)
impl = self.create(items.ImplementationItem)
line = self.create(items.ConnectorItem)
@ -102,7 +123,7 @@ class InterfaceConnectTestCase(TestCase):
def test_glue_when_connector_connected(self):
"""Test interface glueing, when connector connected
"""
iface = self.create(items.InterfaceItem, UML.Component)
iface = self.create(items.InterfaceItem, uml2.Component)
iface.folded = iface.FOLDED_REQUIRED
line1 = self.create(items.ConnectorItem)
@ -118,7 +139,7 @@ class InterfaceConnectTestCase(TestCase):
def test_simple_connection(self):
"""Test simple connection to an interface
"""
iface = self.create(items.InterfaceItem, UML.Component)
iface = self.create(items.InterfaceItem, uml2.Component)
line = self.create(items.ConnectorItem)
iface.folded = iface.FOLDED_PROVIDED
@ -150,7 +171,7 @@ class InterfaceConnectTestCase(TestCase):
def test_connection_angle_change(self):
"""Test angle after connection to an interface
"""
iface = self.create(items.InterfaceItem, UML.Component)
iface = self.create(items.InterfaceItem, uml2.Component)
line = self.create(items.ConnectorItem)
iface.folded = iface.FOLDED_PROVIDED
@ -169,7 +190,7 @@ class InterfaceConnectTestCase(TestCase):
def test_connection_of_two_connectors_one_side(self):
"""Test connection of two connectors to required port of an interface
"""
iface = self.create(items.InterfaceItem, UML.Component)
iface = self.create(items.InterfaceItem, uml2.Component)
c1 = self.create(items.ConnectorItem)
c2 = self.create(items.ConnectorItem)
@ -199,7 +220,7 @@ class InterfaceConnectTestCase(TestCase):
def test_connection_of_two_connectors_two_sides(self):
"""Test connection of two connectors to required and provided ports of an interface
"""
iface = self.create(items.InterfaceItem, UML.Component)
iface = self.create(items.InterfaceItem, uml2.Component)
c1 = self.create(items.ConnectorItem)
c2 = self.create(items.ConnectorItem)
@ -228,7 +249,7 @@ class InterfaceConnectTestCase(TestCase):
def test_simple_disconnection(self):
"""Test disconnection of simple connection to an interface
"""
iface = self.create(items.InterfaceItem, UML.Component)
iface = self.create(items.InterfaceItem, uml2.Component)
line = self.create(items.ConnectorItem)
iface.folded = iface.FOLDED_PROVIDED
@ -264,7 +285,7 @@ class AssemblyConnectorTestCase(TestCase):
List of interface names.
"""
for name in args:
interface = self.element_factory.create(UML.Interface)
interface = self.element_factory.create(uml2.Interface)
interface.name = name
yield interface
@ -273,7 +294,7 @@ class AssemblyConnectorTestCase(TestCase):
"""
Change component's data so it implements interfaces.
"""
impl = self.element_factory.create(UML.Implementation)
impl = self.element_factory.create(uml2.Implementation)
component.implementation = impl
impl.contract = interface
@ -282,7 +303,7 @@ class AssemblyConnectorTestCase(TestCase):
"""
Change component's data so it requires interface.
"""
usage = self.element_factory.create(UML.Usage)
usage = self.element_factory.create(uml2.Usage)
component.clientDependency = usage
usage.supplier = interface
@ -293,8 +314,8 @@ class AssemblyConnectorTestCase(TestCase):
conn1 = self.create(items.ConnectorItem)
conn2 = self.create(items.ConnectorItem)
c1 = self.create(items.ComponentItem, UML.Component)
c2 = self.create(items.ComponentItem, UML.Component)
c1 = self.create(items.ComponentItem, uml2.Component)
c2 = self.create(items.ComponentItem, uml2.Component)
# connect component
self.connect(conn1, conn1.tail, c1)
@ -310,10 +331,10 @@ class AssemblyConnectorTestCase(TestCase):
conn1 = self.create(items.ConnectorItem)
conn2 = self.create(items.ConnectorItem)
c1 = self.create(items.ComponentItem, UML.Component)
c2 = self.create(items.ComponentItem, UML.Component)
c1 = self.create(items.ComponentItem, uml2.Component)
c2 = self.create(items.ComponentItem, uml2.Component)
iface = self.create(items.InterfaceItem, UML.Interface)
iface = self.create(items.InterfaceItem, uml2.Interface)
iface.folded = iface.FOLDED_ASSEMBLY
pport = iface.ports()[0]
rport = iface.ports()[2]
@ -335,7 +356,7 @@ class AssemblyConnectorTestCase(TestCase):
self.assertTrue(conn1.subject is conn2.subject,
'%s is not %s' % (conn1.subject, conn2.subject))
assembly = conn1.subject
self.assertTrue(isinstance(assembly, UML.Connector))
self.assertTrue(isinstance(assembly, uml2.Connector))
self.assertEquals('assembly', assembly.kind)
# there should be two connector ends
@ -366,10 +387,10 @@ class AssemblyConnectorTestCase(TestCase):
conn1 = self.create(items.ConnectorItem)
conn2 = self.create(items.ConnectorItem)
c1 = self.create(items.ComponentItem, UML.Component)
c2 = self.create(items.ComponentItem, UML.Component)
c1 = self.create(items.ComponentItem, uml2.Component)
c2 = self.create(items.ComponentItem, uml2.Component)
iface = self.create(items.InterfaceItem, UML.Interface)
iface = self.create(items.InterfaceItem, uml2.Interface)
iface.folded = iface.FOLDED_ASSEMBLY
pport = iface.ports()[0]
rport = iface.ports()[2]
@ -393,11 +414,11 @@ class AssemblyConnectorTestCase(TestCase):
conn2 = self.create(items.ConnectorItem)
conn3 = self.create(items.ConnectorItem)
c1 = self.create(items.ComponentItem, UML.Component)
c2 = self.create(items.ComponentItem, UML.Component)
c3 = self.create(items.ComponentItem, UML.Component)
c1 = self.create(items.ComponentItem, uml2.Component)
c2 = self.create(items.ComponentItem, uml2.Component)
c3 = self.create(items.ComponentItem, uml2.Component)
iface = self.create(items.InterfaceItem, UML.Interface)
iface = self.create(items.InterfaceItem, uml2.Interface)
iface.folded = iface.FOLDED_ASSEMBLY
pport = iface.ports()[0]
rport = iface.ports()[2]
@ -428,9 +449,9 @@ class AssemblyConnectorTestCase(TestCase):
"""
conn1 = self.create(items.ConnectorItem)
c1 = self.create(items.ComponentItem, UML.Component)
c1 = self.create(items.ComponentItem, uml2.Component)
iface = self.create(items.InterfaceItem, UML.Interface)
iface = self.create(items.InterfaceItem, uml2.Interface)
iface.folded = iface.FOLDED_ASSEMBLY
pport = iface.ports()[0]
rport = iface.ports()[2]
@ -455,10 +476,10 @@ class AssemblyConnectorTestCase(TestCase):
conn1 = self.create(items.ConnectorItem)
conn2 = self.create(items.ConnectorItem)
c1 = self.create(items.ComponentItem, UML.Component)
c2 = self.create(items.ComponentItem, UML.Component)
c1 = self.create(items.ComponentItem, uml2.Component)
c2 = self.create(items.ComponentItem, uml2.Component)
iface = self.create(items.InterfaceItem, UML.Interface)
iface = self.create(items.InterfaceItem, uml2.Interface)
iface.folded = iface.FOLDED_ASSEMBLY
pport = iface.ports()[0]
rport = iface.ports()[2]
@ -488,11 +509,11 @@ class AssemblyConnectorTestCase(TestCase):
conn2 = self.create(items.ConnectorItem)
conn3 = self.create(items.ConnectorItem)
c1 = self.create(items.ComponentItem, UML.Component)
c2 = self.create(items.ComponentItem, UML.Component)
c3 = self.create(items.ComponentItem, UML.Component)
c1 = self.create(items.ComponentItem, uml2.Component)
c2 = self.create(items.ComponentItem, uml2.Component)
c3 = self.create(items.ComponentItem, uml2.Component)
iface = self.create(items.InterfaceItem, UML.Interface)
iface = self.create(items.InterfaceItem, uml2.Interface)
iface.folded = iface.FOLDED_ASSEMBLY
pport = iface.ports()[0]
rport = iface.ports()[2]
@ -543,10 +564,10 @@ class AssemblyConnectorTestCase(TestCase):
conn1 = self.create(items.ConnectorItem)
conn2 = self.create(items.ConnectorItem)
c1 = self.create(items.ComponentItem, UML.Component)
c2 = self.create(items.ComponentItem, UML.Component)
c1 = self.create(items.ComponentItem, uml2.Component)
c2 = self.create(items.ComponentItem, uml2.Component)
iface = self.create(items.InterfaceItem, UML.Interface)
iface = self.create(items.InterfaceItem, uml2.Interface)
iface.folded = iface.FOLDED_ASSEMBLY
pport = iface.ports()[0]
rport = iface.ports()[2]
@ -572,9 +593,9 @@ class AssemblyConnectorTestCase(TestCase):
self.assertTrue(conn1.subject is None)
self.assertTrue(conn2.subject is None)
self.assertEquals(0, len(self.kindof(UML.Connector)))
self.assertEquals(0, len(self.kindof(UML.ConnectorEnd)))
self.assertEquals(0, len(self.kindof(UML.Port)))
self.assertEquals(0, len(self.kindof(uml2.Connector)))
self.assertEquals(0, len(self.kindof(uml2.ConnectorEnd)))
self.assertEquals(0, len(self.kindof(uml2.Port)))
def test_disconnection_order(self):
@ -584,11 +605,11 @@ class AssemblyConnectorTestCase(TestCase):
conn2 = self.create(items.ConnectorItem)
conn3 = self.create(items.ConnectorItem)
c1 = self.create(items.ComponentItem, UML.Component)
c2 = self.create(items.ComponentItem, UML.Component)
c3 = self.create(items.ComponentItem, UML.Component)
c1 = self.create(items.ComponentItem, uml2.Component)
c2 = self.create(items.ComponentItem, uml2.Component)
c3 = self.create(items.ComponentItem, uml2.Component)
iface = self.create(items.InterfaceItem, UML.Interface)
iface = self.create(items.InterfaceItem, uml2.Interface)
iface.folded = iface.FOLDED_ASSEMBLY
pport = iface.ports()[0]
rport = iface.ports()[2]
@ -622,9 +643,9 @@ class AssemblyConnectorTestCase(TestCase):
self.assertTrue(conn2.subject is None)
self.assertTrue(conn3.subject is None)
self.assertEquals(0, len(self.kindof(UML.Connector)))
self.assertEquals(0, len(self.kindof(UML.ConnectorEnd)))
self.assertEquals(0, len(self.kindof(UML.Port)))
self.assertEquals(0, len(self.kindof(uml2.Connector)))
self.assertEquals(0, len(self.kindof(uml2.ConnectorEnd)))
self.assertEquals(0, len(self.kindof(uml2.Port)))

View File

@ -1,3 +1,24 @@
#!/usr/bin/env python
# Copyright (C) 2007-2017 Adam Boduch <adam.boduch@gmail.com>
# Arjan Molenaar <gaphor@gmail.com>
# Artur Wroblewski <wrobell@pld-linux.org>
# Dan Yeaw <dan@yeaw.me>
#
# This file is part of Gaphor.
#
# Gaphor is free software: you can redistribute it and/or modify it under the
# terms of the GNU Library General Public License as published by the Free
# Software Foundation, either version 2 of the License, or (at your option)
# any later version.
#
# Gaphor is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
# more details.
#
# You should have received a copy of the GNU Library General Public
# along with Gaphor. If not, see <http://www.gnu.org/licenses/>.
"""
Connector adapters.
@ -5,15 +26,16 @@ To register connectors implemented in this module, it is imported in
gaphor.adapter package.
"""
from zope import interface, component
from __future__ import absolute_import
from __future__ import print_function
from logging import getLogger
from zope import interface, component
from gaphas import geometry
from gaphor import UML
from gaphor.UML import uml2
from gaphor.core import inject
from gaphor.diagram.interfaces import IConnect
from gaphor.diagram import items
from gaphor.diagram.interfaces import IConnect
logger = getLogger('Connector')
@ -46,30 +68,26 @@ class AbstractConnect(object):
element_factory = inject('element_factory')
def __init__(self, element, line):
self.element = element
self.line = line
self.canvas = self.element.canvas
assert self.canvas == self.element.canvas == self.line.canvas
def get_connection(self, handle):
"""
Get connection information
"""
return self.canvas.get_connection(handle)
return self.canvas.get_connection(handle)
def get_connected(self, handle):
"""
Get item connected to a handle.
"""
cinfo = self.canvas.get_connection(handle)
cinfo = self.canvas.get_connection(handle)
if cinfo is not None:
return cinfo.connected
def get_connected_port(self, handle):
"""
Get port of item connected to connecting item via specified handle.
@ -78,7 +96,6 @@ class AbstractConnect(object):
if cinfo is not None:
return cinfo.port
def allow(self, handle, port):
"""
Determine if items can be connected.
@ -96,7 +113,6 @@ class AbstractConnect(object):
return not count and isinstance(self.line, (items.DependencyItem, items.ImplementationItem))
return True
def connect(self, handle, port):
"""
Connect to an element. Note that at this point the line may
@ -107,12 +123,11 @@ class AbstractConnect(object):
"""
return True
# def reconnect(self, handle, port):
# """
# UML model reconnection method.
# """
# raise NotImplementedError('Reconnection not implemented')
# def reconnect(self, handle, port):
# """
# UML model reconnection method.
# """
# raise NotImplementedError('Reconnection not implemented')
def disconnect(self, handle):
@ -122,7 +137,6 @@ class AbstractConnect(object):
pass
class CommentLineElementConnect(AbstractConnect):
"""
Connect a comment line to any element item.
@ -145,7 +159,7 @@ class CommentLineElementConnect(AbstractConnect):
# Same goes for subjects:
if connected_to and \
(not (connected_to.subject or element.subject)) \
and connected_to.subject is element.subject:
and connected_to.subject is element.subject:
return None
# One end should be connected to a CommentItem:
@ -156,10 +170,10 @@ class CommentLineElementConnect(AbstractConnect):
# Do not allow to links between the comment and the element
if connected_to and element and \
((isinstance(connected_to.subject, UML.Comment) and \
self.element.subject in connected_to.subject.annotatedElement) or \
(isinstance(self.element.subject, UML.Comment) and \
connected_to.subject in self.element.subject.annotatedElement)):
((isinstance(connected_to.subject, uml2.Comment) and \
self.element.subject in connected_to.subject.annotatedElement) or \
(isinstance(self.element.subject, uml2.Comment) and \
connected_to.subject in self.element.subject.annotatedElement)):
return None
return super(CommentLineElementConnect, self).allow(handle, port)
@ -169,7 +183,7 @@ class CommentLineElementConnect(AbstractConnect):
opposite = self.line.opposite(handle)
connected_to = self.get_connected(opposite)
if connected_to:
if isinstance(connected_to.subject, UML.Comment):
if isinstance(connected_to.subject, uml2.Comment):
connected_to.subject.annotatedElement = self.element.subject
else:
self.element.subject.annotatedElement = connected_to.subject
@ -182,15 +196,16 @@ class CommentLineElementConnect(AbstractConnect):
if hct and oct:
logger.debug('Disconnecting %s and %s' % (hct, oct))
try:
if hct.subject and isinstance(oct.subject, UML.Comment):
if hct.subject and isinstance(oct.subject, uml2.Comment):
del oct.subject.annotatedElement[hct.subject]
elif hct.subject and oct.subject:
del hct.subject.annotatedElement[oct.subject]
except ValueError:
logger.debug('Invoked CommentLineElementConnect.disconnect() for nonexistant relationship')
super(CommentLineElementConnect, self).disconnect(handle)
component.provideAdapter(CommentLineElementConnect)
@ -204,7 +219,7 @@ class CommentLineLineConnect(AbstractConnect):
"""
In addition to the normal check, both line ends may not be connected
to the same element. Same goes for subjects.
One of the ends should be connected to a UML.Comment element.
One of the ends should be connected to a uml2.Comment element.
"""
opposite = self.line.opposite(handle)
element = self.element
@ -218,10 +233,10 @@ class CommentLineLineConnect(AbstractConnect):
# Same goes for subjects:
if connected_to and \
(not (connected_to.subject or element.subject)) \
and connected_to.subject is element.subject:
and connected_to.subject is element.subject:
return None
print 'Connecting', element, 'with', element.subject
print('Connecting', element, 'with', element.subject)
# One end should be connected to a CommentItem:
cls = items.CommentItem
@ -236,7 +251,7 @@ class CommentLineLineConnect(AbstractConnect):
opposite = self.line.opposite(handle)
c = self.get_connected(opposite)
if c and self.element.subject:
if isinstance(c.subject, UML.Comment):
if isinstance(c.subject, uml2.Comment):
c.subject.annotatedElement = self.element.subject
else:
self.element.subject.annotatedElement = c.subject
@ -246,12 +261,13 @@ class CommentLineLineConnect(AbstractConnect):
opposite = self.line.opposite(handle)
c2 = self.get_connected(opposite)
if c1 and c2:
if isinstance(c1.subject, UML.Comment):
if isinstance(c1.subject, uml2.Comment):
del c1.subject.annotatedElement[c2.subject]
elif c2.subject:
del c2.subject.annotatedElement[c1.subject]
super(CommentLineLineConnect, self).disconnect(handle)
component.provideAdapter(CommentLineLineConnect)
@ -269,7 +285,6 @@ class UnaryRelationshipConnect(AbstractConnect):
element_factory = inject('element_factory')
def relationship(self, required_type, head, tail):
"""
Find an existing relationship in the model that meets the
@ -287,8 +302,8 @@ class UnaryRelationshipConnect(AbstractConnect):
# First check if the right subject is already connected:
if line.subject \
and getattr(line.subject, head.name) is head_subject \
and getattr(line.subject, tail.name) is tail_subject:
and getattr(line.subject, head.name) is head_subject \
and getattr(line.subject, tail.name) is tail_subject:
return line.subject
# Try to find a relationship, that is already created, but not
@ -296,7 +311,7 @@ class UnaryRelationshipConnect(AbstractConnect):
for gen in getattr(tail_subject, tail.opposite):
if not isinstance(gen, required_type):
continue
gen_head = getattr(gen, head.name)
try:
if not head_subject in gen_head:
@ -327,7 +342,6 @@ class UnaryRelationshipConnect(AbstractConnect):
setattr(relation, tail.name, self.get_connected(line.tail).subject)
return relation
def reconnect_relationship(self, handle, head, tail):
"""
Reconnect relationship for given handle.
@ -350,7 +364,6 @@ class UnaryRelationshipConnect(AbstractConnect):
else:
raise ValueError('Incorrect handle passed to adapter')
def connect_connected_items(self, connections=None):
"""
Cause items connected to ``line`` to reconnect, allowing them to
@ -366,7 +379,7 @@ class UnaryRelationshipConnect(AbstractConnect):
adapter = component.queryMultiAdapter((line, cinfo.connected), IConnect)
assert adapter
adapter.connect(cinfo.handle, cinfo.port)
def disconnect_connected_items(self):
"""
Cause items connected to @line to be disconnected.
@ -392,7 +405,7 @@ class UnaryRelationshipConnect(AbstractConnect):
"""
Establish the relationship at model level.
"""
raise NotImplementedError, 'Implement connect_subject() in a subclass'
raise NotImplementedError('Implement connect_subject() in a subclass')
def disconnect_subject(self, handle):
"""
@ -421,7 +434,6 @@ class UnaryRelationshipConnect(AbstractConnect):
self.connect_connected_items()
return True
def disconnect(self, handle):
"""
Disconnect model element.
@ -430,13 +442,13 @@ class UnaryRelationshipConnect(AbstractConnect):
opposite = line.opposite(handle)
oct = self.get_connected(opposite)
hct = self.get_connected(handle)
if hct and oct:
# Both sides of line are connected => disconnect
old = line.subject
connections = self.disconnect_connected_items()
self.disconnect_subject(handle)
if old:
self.connect_connected_items(connections)
@ -465,10 +477,9 @@ class RelationshipConnect(UnaryRelationshipConnect):
# Same goes for subjects:
if connected_to and \
(not (connected_to.subject or element.subject)) \
and connected_to.subject is element.subject:
and connected_to.subject is element.subject:
return None
return super(RelationshipConnect, self).allow(handle, port)
# vim:sw=4:et:ai

View File

@ -1,13 +1,34 @@
#!/usr/bin/env python
# Copyright (C) 2007-2017 Arjan Molenaar <gaphor@gmail.com>
# Artur Wroblewski <wrobell@pld-linux.org>
# Dan Yeaw <dan@yeaw.me>
#
# This file is part of Gaphor.
#
# Gaphor is free software: you can redistribute it and/or modify it under the
# terms of the GNU Library General Public License as published by the Free
# Software Foundation, either version 2 of the License, or (at your option)
# any later version.
#
# Gaphor is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
# more details.
#
# You should have received a copy of the GNU Library General Public
# along with Gaphor. If not, see <http://www.gnu.org/licenses/>.
"""
Adapters
"""
from __future__ import absolute_import
from zope import interface, component
from gaphas.item import NW, SE
from gaphas import geometry
from gaphas import constraint
from gaphor import UML
from gaphor.UML import uml2, umllex
from gaphor.core import inject
from gaphor.diagram.interfaces import IEditor
from gaphor.diagram import items
@ -25,7 +46,7 @@ def editable(el):
return el
@editable.when_type(UML.Slot)
@editable.when_type(uml2.Slot)
def editable_slot(el):
"""
Return editable part of a slot.
@ -152,13 +173,13 @@ class CompartmentItemEditor(object):
return bool(self._edit and self._edit.subject)
def get_text(self):
return UML.format(editable(self._edit.subject))
return format(editable(self._edit.subject))
def get_bounds(self):
return None
def update_text(self, text):
UML.parse(editable(self._edit.subject), text)
umllex.parse(editable(self._edit.subject), text)
def key_pressed(self, pos, key):
pass
@ -192,14 +213,14 @@ class AssociationItemEditor(object):
def get_text(self):
if self._edit is self._item:
return self._edit.subject.name
return UML.format(self._edit.subject, visibility=True,
return format(self._edit.subject, visibility=True,
is_derived=True, type=True,
multiplicity=True, default=True)
def get_bounds(self):
return None
def update_text(self, text):
UML.parse(self._edit.subject, text)
uml2.parse(self._edit.subject, text)
def key_pressed(self, pos, key):
pass

View File

@ -1,3 +1,23 @@
#!/usr/bin/env python
# Copyright (C) 2007-2017 Arjan Molenaar <gaphor@gmail.com>
# Artur Wroblewski <wrobell@pld-linux.org>
# Dan Yeaw <dan@yeaw.me>
#
# This file is part of Gaphor.
#
# Gaphor is free software: you can redistribute it and/or modify it under the
# terms of the GNU Library General Public License as published by the Free
# Software Foundation, either version 2 of the License, or (at your option)
# any later version.
#
# Gaphor is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
# more details.
#
# You should have received a copy of the GNU Library General Public
# along with Gaphor. If not, see <http://www.gnu.org/licenses/>.
"""
Grouping functionality allows to nest one item within another item (parent
item). This is useful in several use cases
@ -15,9 +35,10 @@ is about to be created. Therefore `AbstractGroup.can_contain` has
to be aware that `AbstractGroup.item` can be null.
"""
from __future__ import absolute_import
from zope import interface, component
from gaphor import UML
from gaphor.UML import uml2
from gaphor.core import inject
from gaphor.diagram import items
from gaphor.diagram.interfaces import IGroup
@ -52,14 +73,14 @@ class AbstractGroup(object):
"""
Group an item within parent.
"""
raise NotImplemented, 'This is abstract method'
raise NotImplemented('This is abstract method')
def ungroup(self):
"""
Remove item from parent.
"""
raise NotImplemented, 'This is abstract method'
raise NotImplemented('This is abstract method')
@ -107,18 +128,18 @@ class NodeComponentGroup(AbstractGroup):
component = self.item.subject
# node attribute
a1 = self.element_factory.create(UML.Property)
a1 = self.element_factory.create(uml2.Property)
a1.aggregation = 'composite'
# component attribute
a2 = self.element_factory.create(UML.Property)
a2 = self.element_factory.create(uml2.Property)
e1 = self.element_factory.create(UML.ConnectorEnd)
e2 = self.element_factory.create(UML.ConnectorEnd)
e1 = self.element_factory.create(uml2.ConnectorEnd)
e2 = self.element_factory.create(uml2.ConnectorEnd)
# create connection between node and component
e1.role = a1
e2.role = a2
connector = self.element_factory.create(UML.Connector)
connector = self.element_factory.create(uml2.Connector)
connector.end = e1
connector.end = e2
@ -157,7 +178,7 @@ class NodeArtifactGroup(AbstractGroup):
artifact = self.item.subject
# deploy artifact on node
deployment = self.element_factory.create(UML.Deployment)
deployment = self.element_factory.create(uml2.Deployment)
node.deployment = deployment
deployment.deployedArtifact = artifact
@ -208,7 +229,7 @@ class ActivityPartitionsGroup(AbstractGroup):
def group(self):
p = self.parent.subject
sp = self.element_factory.create(UML.ActivityPartition)
sp = self.element_factory.create(uml2.ActivityPartition)
self.item.subject = sp
sp.name = 'Swimlane'
if p:

View File

@ -0,0 +1,18 @@
#!/usr/bin/env python
# Copyright (C) 2001-2009 Arjan Molenaar <gaphor@gmail.com>
#
# This file is part of Gaphor.
#
# Gaphor is free software: you can redistribute it and/or modify it under the
# terms of the GNU Library General Public License as published by the Free
# Software Foundation, either version 2 of the License, or (at your option)
# any later version.
#
# Gaphor is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
# more details.
#
# You should have received a copy of the GNU Library General Public
# along with Gaphor. If not, see <http://www.gnu.org/licenses/>.

View File

@ -1,10 +1,31 @@
#!/usr/bin/env python
# Copyright (C) 2009-2017 Arjan Molenaar <gaphor@gmail.com>
# Artur Wroblewski <wrobell@pld-linux.org>
# Dan Yeaw <dan@yeaw.me>
#
# This file is part of Gaphor.
#
# Gaphor is free software: you can redistribute it and/or modify it under the
# terms of the GNU Library General Public License as published by the Free
# Software Foundation, either version 2 of the License, or (at your option)
# any later version.
#
# Gaphor is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
# more details.
#
# You should have received a copy of the GNU Library General Public
# along with Gaphor. If not, see <http://www.gnu.org/licenses/>.
"""
Message item connection adapters.
"""
from __future__ import absolute_import
from gaphor.adapters.connectors import AbstractConnect
from zope import interface, component
from gaphor import UML
from gaphor.UML import uml2
from gaphor.diagram import items
class MessageLifelineConnect(AbstractConnect):
@ -25,7 +46,7 @@ class MessageLifelineConnect(AbstractConnect):
"""
def get_subject():
if not line.subject:
message = self.element_factory.create(UML.Message)
message = self.element_factory.create(uml2.Message)
message.name = 'call()'
line.subject = message
return line.subject
@ -33,14 +54,14 @@ class MessageLifelineConnect(AbstractConnect):
if send:
message = get_subject()
if not message.sendEvent:
event = self.element_factory.create(UML.MessageOccurrenceSpecification)
event = self.element_factory.create(uml2.MessageOccurrenceSpecification)
event.sendMessage = message
event.covered = send.subject
if received:
message = get_subject()
if not message.receiveEvent:
event = self.element_factory.create(UML.MessageOccurrenceSpecification)
event = self.element_factory.create(uml2.MessageOccurrenceSpecification)
event.receiveMessage = message
event.covered = received.subject

View File

@ -0,0 +1,18 @@
#!/usr/bin/env python
# Copyright (C) 2001-2009 Arjan Molenaar <gaphor@gmail.com>
#
# This file is part of Gaphor.
#
# Gaphor is free software: you can redistribute it and/or modify it under the
# terms of the GNU Library General Public License as published by the Free
# Software Foundation, either version 2 of the License, or (at your option)
# any later version.
#
# Gaphor is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
# more details.
#
# You should have received a copy of the GNU Library General Public
# along with Gaphor. If not, see <http://www.gnu.org/licenses/>.

View File

@ -1,9 +1,30 @@
#!/usr/bin/env python
# Copyright (C) 2009-2017 Arjan Molenaar <gaphor@gmail.com>
# Artur Wroblewski <wrobell@pld-linux.org>
# Dan Yeaw <dan@yeaw.me>
#
# This file is part of Gaphor.
#
# Gaphor is free software: you can redistribute it and/or modify it under the
# terms of the GNU Library General Public License as published by the Free
# Software Foundation, either version 2 of the License, or (at your option)
# any later version.
#
# Gaphor is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
# more details.
#
# You should have received a copy of the GNU Library General Public
# along with Gaphor. If not, see <http://www.gnu.org/licenses/>.
"""
Message connection adapter tests.
"""
from __future__ import absolute_import
from gaphor.tests import TestCase
from gaphor import UML
from gaphor.UML import uml2, modelfactory
from gaphor.diagram import items
class BasicMessageConnectionsTestCase(TestCase):
@ -55,8 +76,8 @@ class BasicMessageConnectionsTestCase(TestCase):
self.assertTrue(msg.subject is not None)
self.assertEquals(msg.subject.messageKind, 'lost')
messages = self.kindof(UML.Message)
occurences = self.kindof(UML.MessageOccurrenceSpecification)
messages = self.kindof(uml2.Message)
occurences = self.kindof(uml2.MessageOccurrenceSpecification)
self.assertEquals(1, len(messages))
self.assertEquals(1, len(occurences))
@ -76,8 +97,8 @@ class BasicMessageConnectionsTestCase(TestCase):
self.assertTrue(msg.subject is not None)
self.assertEquals(msg.subject.messageKind, 'found')
messages = self.kindof(UML.Message)
occurences = self.kindof(UML.MessageOccurrenceSpecification)
messages = self.kindof(uml2.Message)
occurences = self.kindof(uml2.MessageOccurrenceSpecification)
self.assertEquals(1, len(messages))
self.assertEquals(1, len(occurences))
@ -99,8 +120,8 @@ class BasicMessageConnectionsTestCase(TestCase):
self.assertTrue(msg.subject is not None)
self.assertEquals(msg.subject.messageKind, 'complete')
messages = self.kindof(UML.Message)
occurences = self.kindof(UML.MessageOccurrenceSpecification)
messages = self.kindof(uml2.Message)
occurences = self.kindof(uml2.MessageOccurrenceSpecification)
self.assertEquals(1, len(messages))
self.assertEquals(2, len(occurences))
@ -245,19 +266,19 @@ class DiagramModeMessageConnectionTestCase(TestCase):
assert subject.sendEvent and subject.receiveEvent
# add some more messages
m1 = UML.model.create_message(factory, subject)
m2 = UML.model.create_message(factory, subject)
m1 = modelfactory.create_message(factory, subject)
m2 = modelfactory.create_message(factory, subject)
msg.add_message(m1, False)
msg.add_message(m2, False)
# add some inverted messages
m3 = UML.model.create_message(factory, subject, True)
m4 = UML.model.create_message(factory, subject, True)
m3 = modelfactory.create_message(factory, subject, True)
m4 = modelfactory.create_message(factory, subject, True)
msg.add_message(m3, True)
msg.add_message(m4, True)
messages = list(self.kindof(UML.Message))
occurences = set(self.kindof(UML.MessageOccurrenceSpecification))
messages = list(self.kindof(uml2.Message))
occurences = set(self.kindof(uml2.MessageOccurrenceSpecification))
# verify integrity of messages
self.assertEquals(5, len(messages))
@ -278,7 +299,7 @@ class DiagramModeMessageConnectionTestCase(TestCase):
# no message after full disconnection
self.disconnect(msg, msg.tail)
self.assertEquals(0, len(self.kindof(UML.Message)))
self.assertEquals(0, len(self.kindof(uml2.Message)))
# vim:sw=4:et:ai

View File

@ -0,0 +1,18 @@
#!/usr/bin/env python
# Copyright (C) 2001-2009 Arjan Molenaar <gaphor@gmail.com>
#
# This file is part of Gaphor.
#
# Gaphor is free software: you can redistribute it and/or modify it under the
# terms of the GNU Library General Public License as published by the Free
# Software Foundation, either version 2 of the License, or (at your option)
# any later version.
#
# Gaphor is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
# more details.
#
# You should have received a copy of the GNU Library General Public
# along with Gaphor. If not, see <http://www.gnu.org/licenses/>.

View File

@ -1,6 +1,27 @@
#!/usr/bin/env python
# Copyright (C) 2009-2017 Arjan Molenaar <gaphor@gmail.com>
# Artur Wroblewski <wrobell@pld-linux.org>
# Dan Yeaw <dan@yeaw.me>
#
# This file is part of Gaphor.
#
# Gaphor is free software: you can redistribute it and/or modify it under the
# terms of the GNU Library General Public License as published by the Free
# Software Foundation, either version 2 of the License, or (at your option)
# any later version.
#
# Gaphor is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
# more details.
#
# You should have received a copy of the GNU Library General Public
# along with Gaphor. If not, see <http://www.gnu.org/licenses/>.
from __future__ import absolute_import
from gaphor.adapters.connectors import RelationshipConnect
from zope import interface, component
from gaphor import UML
from gaphor.UML import uml2, modelfactory
from gaphor.diagram import items
@ -17,10 +38,10 @@ class ExtensionConnect(RelationshipConnect):
if handle is line.head:
# Element at the head should be a class
# (implies stereotype as well)
allow = isinstance(subject, UML.Class)
allow = isinstance(subject, uml2.Class)
elif handle is line.tail:
# Element at the tail should be a stereotype
allow = isinstance(subject, UML.Stereotype)
allow = isinstance(subject, uml2.Stereotype)
return allow and super(ExtensionConnect, self).allow(handle, port)
@ -49,7 +70,7 @@ class ExtensionConnect(RelationshipConnect):
# Find all associations and determine if the properties on
# the association ends have a type that points to the class.
for assoc in self.element_factory.select():
if isinstance(assoc, UML.Extension):
if isinstance(assoc, uml2.Extension):
end1 = assoc.memberEnd[0]
end2 = assoc.memberEnd[1]
if (end1.type is head_type and end2.type is tail_type) \
@ -64,7 +85,7 @@ class ExtensionConnect(RelationshipConnect):
return
else:
# Create a new Extension relationship
relation = UML.model.extend_with_stereotype(self.element_factory,
relation = modelfactory.extend_with_stereotype(self.element_factory,
head_type,
tail_type)
line.subject = relation

View File

@ -1,7 +1,28 @@
#!/usr/bin/env python
# Copyright (C) 2009-2017 Arjan Molenaar <gaphor@gmail.com>
# Artur Wroblewski <wrobell@pld-linux.org>
# Dan Yeaw <dan@yeaw.me>
#
# This file is part of Gaphor.
#
# Gaphor is free software: you can redistribute it and/or modify it under the
# terms of the GNU Library General Public License as published by the Free
# Software Foundation, either version 2 of the License, or (at your option)
# any later version.
#
# Gaphor is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
# more details.
#
# You should have received a copy of the GNU Library General Public
# along with Gaphor. If not, see <http://www.gnu.org/licenses/>.
"""
Metaclass item editors.
"""
from __future__ import absolute_import
import gtk
from gaphor.core import _, inject, transactional
@ -9,7 +30,7 @@ from gaphor.ui.interfaces import IPropertyPage
from zope import interface, component
from gaphor.diagram import items
from gaphor.adapters.propertypages import create_hbox_label, EventWatcher
from gaphor import UML
from gaphor.UML import uml2
def _issubclass(c, b):
try:
@ -30,8 +51,8 @@ class MetaclassNameEditor(object):
NAME_LABEL = _('Name')
CLASSES = list(sorted(n for n in dir(UML)
if _issubclass(getattr(UML, n), UML.Element) and n != 'Stereotype'))
CLASSES = list(sorted(n for n in dir(uml2)
if _issubclass(getattr(uml2, n), uml2.Element) and n != 'Stereotype'))
def __init__(self, item):

View File

@ -1,14 +1,35 @@
#!/usr/bin/env python
# Copyright (C) 2009-2017 Arjan Molenaar <gaphor@gmail.com>
# Artur Wroblewski <wrobell@pld-linux.org>
# Dan Yeaw <dan@yeaw.me>
#
# This file is part of Gaphor.
#
# Gaphor is free software: you can redistribute it and/or modify it under the
# terms of the GNU Library General Public License as published by the Free
# Software Foundation, either version 2 of the License, or (at your option)
# any later version.
#
# Gaphor is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
# more details.
#
# You should have received a copy of the GNU Library General Public
# along with Gaphor. If not, see <http://www.gnu.org/licenses/>.
"""
Stereotype property page.
"""
from __future__ import absolute_import
from __future__ import print_function
import gtk
from gaphor.core import _, inject, transactional
from gaphor.ui.interfaces import IPropertyPage
from gaphor.diagram import items
from gaphor.diagram.diagramitem import StereotypeSupport
from zope import interface, component
from gaphor import UML
from gaphor.UML import uml2, modelfactory
from gaphor.adapters.propertypages import on_text_cell_edited, on_bool_cell_edited
class StereotypeAttributes(gtk.TreeStore):
@ -26,7 +47,7 @@ class StereotypeAttributes(gtk.TreeStore):
def refresh(self):
self.clear()
subject = self.subject
stereotypes = UML.model.get_stereotypes(self.element_factory, subject)
stereotypes = modelfactory.get_stereotypes(self.element_factory, subject)
instances = self.subject.appliedStereotype
# shortcut map stereotype -> slot (InstanceSpecification)
@ -66,7 +87,7 @@ class StereotypeAttributes(gtk.TreeStore):
elif col == 1:
self.set_slot_value(iter, value)
else:
print 'col', col
print('col', col)
def select_stereotype(self, iter):
"""
@ -81,9 +102,9 @@ class StereotypeAttributes(gtk.TreeStore):
subject = self.subject
if value:
UML.model.apply_stereotype(self.element_factory, subject, stereotype)
modelfactory.apply_stereotype(self.element_factory, subject, stereotype)
else:
UML.model.remove_stereotype(subject, stereotype)
modelfactory.remove_stereotype(subject, stereotype)
row[2] = value
@ -99,7 +120,7 @@ class StereotypeAttributes(gtk.TreeStore):
path = self.get_path(iter)
row = self[path]
name, old_value, is_applied, attr, obj, slot = row
if isinstance(attr, UML.Stereotype):
if isinstance(attr, uml2.Stereotype):
return # don't edit stereotype rows
log.debug('editing %s' % list(row))
@ -108,7 +129,7 @@ class StereotypeAttributes(gtk.TreeStore):
return # nothing to do and don't create slot without value
if slot is None:
slot = UML.model.add_slot(self.element_factory, obj, attr)
slot = modelfactory.add_slot(self.element_factory, obj, attr)
assert slot
@ -149,7 +170,7 @@ def create_stereotype_tree_view(model):
#value = model.get_value(iter, 4)
#cell.set_property('active', value is not None)
value = model.get_value(iter, 3)
cell.set_property('visible', isinstance(value, UML.Stereotype))
cell.set_property('visible', isinstance(value, uml2.Stereotype))
col.set_cell_data_func(renderer, show_checkbox)
renderer = gtk.CellRendererText()
@ -197,11 +218,11 @@ class StereotypePage(object):
if subject is None:
return None
stereotypes = UML.model.get_stereotypes(self.element_factory, subject)
stereotypes = modelfactory.get_stereotypes(self.element_factory, subject)
if not stereotypes:
return None
#applied = set(UML.model.get_applied_stereotypes(subject))
#applied = set(modelfactory.get_applied_stereotypes(subject))
#for i, stereotype in enumerate(stereotypes):
# if (i % 3) == 0:
# hbox = gtk.HBox(spacing=20)
@ -235,9 +256,9 @@ class StereotypePage(object):
#def _on_stereotype_selected(self, button, stereotype):
# subject = self.item.subject
# if button.get_active():
# UML.model.apply_stereotype(self.element_factory, subject, stereotype)
# modelfactory.apply_stereotype(self.element_factory, subject, stereotype)
# else:
# UML.model.remove_stereotype(subject, stereotype)
# modelfactory.remove_stereotype(subject, stereotype)
# self.model.refresh()
@ -248,7 +269,7 @@ class StereotypePage(object):
component.provideAdapter(StereotypePage,
adapts=[UML.Element],
adapts=[uml2.Element],
name='Stereotypes')

View File

@ -0,0 +1,18 @@
#!/usr/bin/env python
# Copyright (C) 2001-2009 Arjan Molenaar <gaphor@gmail.com>
#
# This file is part of Gaphor.
#
# Gaphor is free software: you can redistribute it and/or modify it under the
# terms of the GNU Library General Public License as published by the Free
# Software Foundation, either version 2 of the License, or (at your option)
# any later version.
#
# Gaphor is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
# more details.
#
# You should have received a copy of the GNU Library General Public
# along with Gaphor. If not, see <http://www.gnu.org/licenses/>.

View File

@ -1,9 +1,29 @@
#!/usr/bin/env python
# Copyright (C) 2009-2017 Arjan Molenaar <gaphor@gmail.com>
# Dan Yeaw <dan@yeaw.me>
#
# This file is part of Gaphor.
#
# Gaphor is free software: you can redistribute it and/or modify it under the
# terms of the GNU Library General Public License as published by the Free
# Software Foundation, either version 2 of the License, or (at your option)
# any later version.
#
# Gaphor is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
# more details.
#
# You should have received a copy of the GNU Library General Public
# along with Gaphor. If not, see <http://www.gnu.org/licenses/>.
"""
Extension item connection adapter tests.
"""
from __future__ import absolute_import
from gaphor.tests import TestCase
from gaphor import UML
from gaphor.UML import uml2
from gaphor.diagram import items
class ExtensionConnectorTestCase(TestCase):
@ -14,7 +34,7 @@ class ExtensionConnectorTestCase(TestCase):
"""Test extension item glueing to a class
"""
ext = self.create(items.ExtensionItem)
cls = self.create(items.ClassItem, UML.Class)
cls = self.create(items.ClassItem, uml2.Class)
# cannot connect extension item tail to a class
glued = self.allow(ext, ext.tail, cls)
@ -25,10 +45,10 @@ class ExtensionConnectorTestCase(TestCase):
"""Test extension item glueing to a stereotype
"""
ext = self.create(items.ExtensionItem)
st = self.create(items.ClassItem, UML.Stereotype)
st = self.create(items.ClassItem, uml2.Stereotype)
# test precondition
assert type(st.subject) is UML.Stereotype
assert type(st.subject) is uml2.Stereotype
# can connect extension item head to a Stereotype UML metaclass,
# because it derives from Class UML metaclass
@ -40,8 +60,8 @@ class ExtensionConnectorTestCase(TestCase):
"""Test extension item glue
"""
ext = self.create(items.ExtensionItem)
st = self.create(items.ClassItem, UML.Stereotype)
cls = self.create(items.ClassItem, UML.Class)
st = self.create(items.ClassItem, uml2.Stereotype)
cls = self.create(items.ClassItem, uml2.Class)
glued = self.allow(ext, ext.tail, st)
self.assertTrue(glued)
@ -56,8 +76,8 @@ class ExtensionConnectorTestCase(TestCase):
"""Test extension item connection
"""
ext = self.create(items.ExtensionItem)
st = self.create(items.ClassItem, UML.Stereotype)
cls = self.create(items.ClassItem, UML.Class)
st = self.create(items.ClassItem, uml2.Stereotype)
cls = self.create(items.ClassItem, uml2.Class)
self.connect(ext, ext.tail, st)
self.connect(ext, ext.head, cls)

View File

@ -1,14 +1,33 @@
#!/usr/bin/env python
# Copyright (C) 2010-2017 Arjan Molenaar <gaphor@gmail.com>
# Dan Yeaw <dan@yeaw.me>
#
# This file is part of Gaphor.
#
# Gaphor is free software: you can redistribute it and/or modify it under the
# terms of the GNU Library General Public License as published by the Free
# Software Foundation, either version 2 of the License, or (at your option)
# any later version.
#
# Gaphor is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
# more details.
#
# You should have received a copy of the GNU Library General Public
# along with Gaphor. If not, see <http://www.gnu.org/licenses/>.
from __future__ import absolute_import
from gaphor.tests import TestCase
from gaphor.adapters.profiles.metaclasseditor import MetaclassNameEditor
from gaphor.diagram import items
from gaphor import UML
from gaphor.UML import uml2
import gtk
class MetaclassEditorTest(TestCase):
def test_name_selection(self):
ci = self.create(items.MetaclassItem, UML.Class)
ci = self.create(items.MetaclassItem, uml2.Class)
ci.subject.name = 'Class'
editor = MetaclassNameEditor(ci)
page = editor.construct()

View File

@ -1,3 +1,23 @@
#!/usr/bin/env python
# Copyright (C) 2007-2017 Arjan Molenaar <gaphor@gmail.com>
# Artur Wroblewski <wrobell@pld-linux.org>
# Dan Yeaw <dan@yeaw.me>
#
# This file is part of Gaphor.
#
# Gaphor is free software: you can redistribute it and/or modify it under the
# terms of the GNU Library General Public License as published by the Free
# Software Foundation, either version 2 of the License, or (at your option)
# any later version.
#
# Gaphor is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
# more details.
#
# You should have received a copy of the GNU Library General Public
# along with Gaphor. If not, see <http://www.gnu.org/licenses/>.
"""
Adapters for the Property Editor.
@ -26,6 +46,8 @@ TODO:
"""
from __future__ import absolute_import
from __future__ import print_function
import gobject
import gtk
import math
@ -34,10 +56,11 @@ from gaphor.services.elementdispatcher import EventWatcher
from gaphor.ui.interfaces import IPropertyPage
from gaphor.diagram import items
from zope import interface, component
from gaphor import UML
from gaphor.UML.interfaces import IAttributeChangeEvent
from gaphor.UML import uml2, modelfactory
import gaphas.item
from gaphas.decorators import async
from six.moves import range
from six.moves import zip
class EditableTreeModel(gtk.ListStore):
"""
@ -198,11 +221,11 @@ class ClassAttributes(EditableTreeModel):
def _get_rows(self):
for attr in self._item.subject.ownedAttribute:
if not attr.association:
yield [UML.format(attr), attr.isStatic, attr]
yield [format(attr), attr.isStatic, attr]
def _create_object(self):
attr = self.element_factory.create(UML.Property)
attr = self.element_factory.create(uml2.Property)
self._item.subject.ownedAttribute = attr
return attr
@ -211,14 +234,14 @@ class ClassAttributes(EditableTreeModel):
def _set_object_value(self, row, col, value):
attr = row[-1]
if col == 0:
UML.parse(attr, value)
row[0] = UML.format(attr)
parse(attr, value)
row[0] = format(attr)
elif col == 1:
attr.isStatic = not attr.isStatic
row[1] = attr.isStatic
elif col == 2:
# Value in attribute object changed:
row[0] = UML.format(attr)
row[0] = format(attr)
row[1] = attr.isStatic
@ -234,11 +257,11 @@ class ClassOperations(EditableTreeModel):
def _get_rows(self):
for operation in self._item.subject.ownedOperation:
yield [UML.format(operation), operation.isAbstract, operation.isStatic, operation]
yield [format(operation), operation.isAbstract, operation.isStatic, operation]
def _create_object(self):
operation = self.element_factory.create(UML.Operation)
operation = self.element_factory.create(uml2.Operation)
self._item.subject.ownedOperation = operation
return operation
@ -247,8 +270,8 @@ class ClassOperations(EditableTreeModel):
def _set_object_value(self, row, col, value):
operation = row[-1]
if col == 0:
UML.parse(operation, value)
row[0] = UML.format(operation)
parse(operation, value)
row[0] = format(operation)
elif col == 1:
operation.isAbstract = not operation.isAbstract
row[1] = operation.isAbstract
@ -256,7 +279,7 @@ class ClassOperations(EditableTreeModel):
operation.isStatic = not operation.isStatic
row[2] = operation.isStatic
elif col == 3:
row[0] = UML.format(operation)
row[0] = format(operation)
row[1] = operation.isAbstract
row[2] = operation.isStatic
@ -296,7 +319,7 @@ class CommunicationMessageModel(EditableTreeModel):
def _create_object(self):
item = self._item
subject = item.subject
message = UML.model.create_message(self.element_factory, subject, self.inverted)
message = modelfactory.create_message(self.element_factory, subject, self.inverted)
item.add_message(message, self.inverted)
return message
@ -455,7 +478,7 @@ def create_tree_view(model, names, tip='', ro_cols=None):
tree_view.set_rules_hint(True)
n = model.get_n_columns() - 1
for name, i in zip(names, range(n)):
for name, i in zip(names, list(range(n))):
col_type = model.get_column_type(i)
if col_type == gobject.TYPE_STRING:
renderer = gtk.CellRendererText()
@ -491,7 +514,7 @@ class CommentItemPropertyPage(object):
Property page for Comments
"""
interface.implements(IPropertyPage)
component.adapts(UML.Comment)
component.adapts(uml2.Comment)
order = 0
@ -549,14 +572,14 @@ class NamedElementPropertyPage(object):
"""
interface.implements(IPropertyPage)
component.adapts(UML.NamedElement)
component.adapts(uml2.NamedElement)
order = 10
NAME_LABEL = _('Name')
def __init__(self, subject):
assert subject is None or isinstance(subject, UML.NamedElement), '%s' % type(subject)
assert subject is None or isinstance(subject, uml2.NamedElement), '%s' % type(subject)
self.subject = subject
self.watcher = EventWatcher(subject)
self.size_group = gtk.SizeGroup(gtk.SIZE_GROUP_HORIZONTAL)
@ -611,7 +634,7 @@ class ClassPropertyPage(NamedElementPropertyPage):
Adapter which shows a property page for a class view.
"""
component.adapts(UML.Class)
component.adapts(uml2.Class)
def __init__(self, subject):
super(ClassPropertyPage, self).__init__(subject)
@ -875,10 +898,10 @@ class DependencyPropertyPage(object):
element_factory = inject('element_factory')
DEPENDENCY_TYPES = (
(_('Dependency'), UML.Dependency),
(_('Usage'), UML.Usage),
(_('Realization'), UML.Realization),
(_('Implementation'), UML.Implementation))
(_('Dependency'), uml2.Dependency),
(_('Usage'), uml2.Usage),
(_('Realization'), uml2.Realization),
(_('Implementation'), uml2.Implementation))
def __init__(self, item):
super(DependencyPropertyPage, self).__init__()
@ -1029,7 +1052,7 @@ class AssociationPropertyPage(NamedItemPropertyPage):
for name, adapter in component.getAdapters([item,], IPropertyPage):
adaptermap[name] = (adapter.order, name, adapter)
adapters = adaptermap.values()
adapters = list(adaptermap.values())
adapters.sort()
return adapters
@ -1057,7 +1080,7 @@ class AssociationPropertyPage(NamedItemPropertyPage):
expander.add(page)
expander.show_all()
vbox.pack_start(expander, expand=False)
except Exception, e:
except Exception as e:
log.error('Could not construct property page for ' + name, exc_info=True)
component.provideAdapter(AssociationPropertyPage, name='Properties')
@ -1069,7 +1092,7 @@ class AssociationEndPropertyPage(object):
"""
interface.implements(IPropertyPage)
component.adapts(UML.Property)
component.adapts(uml2.Property)
order = 0
@ -1083,17 +1106,17 @@ class AssociationEndPropertyPage(object):
vbox = gtk.VBox()
entry = gtk.Entry()
#entry.set_text(UML.format(self.subject, visibility=True, is_derived=Truemultiplicity=True) or '')
#entry.set_text(format(self.subject, visibility=True, is_derived=Truemultiplicity=True) or '')
# monitor subject attribute (all, cause it contains many children)
changed_id = entry.connect('changed', self._on_end_name_change)
def handler(event):
if not entry.props.has_focus:
entry.handler_block(changed_id)
entry.set_text(UML.format(self.subject,
entry.set_text(format(self.subject,
visibility=True, is_derived=True,
multiplicity=True) or '')
#entry.set_text(UML.format(self.subject, multiplicity=True) or '')
#entry.set_text(format(self.subject, multiplicity=True) or '')
entry.handler_unblock(changed_id)
handler(None)
@ -1139,12 +1162,12 @@ Enter attribute name and multiplicity, for example
@transactional
def _on_end_name_change(self, entry):
UML.parse(self.subject, entry.get_text())
parse(self.subject, entry.get_text())
@transactional
def _on_navigability_change(self, combo):
nav = self.NAVIGABILITY[combo.get_active()]
UML.model.set_navigability(self.subject.association, self.subject, nav)
modelfactory.set_navigability(self.subject.association, self.subject, nav)
@transactional
def _on_aggregation_change(self, combo):
@ -1291,7 +1314,7 @@ class JoinNodePropertyPage(NamedItemPropertyPage):
hbox = gtk.HBox()
page.pack_start(hbox, expand=False)
if isinstance(subject, UML.JoinNode):
if isinstance(subject, uml2.JoinNode):
hbox = create_hbox_label(self, page, _('Join specification'))
entry = gtk.Entry()
entry.set_text(subject.joinSpec or '')
@ -1311,7 +1334,7 @@ class JoinNodePropertyPage(NamedItemPropertyPage):
@transactional
def _on_join_spec_change(self, entry):
value = entry.get_text().strip()
print 'new joinspec', value
print('new joinspec', value)
self.subject.joinSpec = value
def _on_horizontal_change(self, button):
@ -1362,10 +1385,10 @@ class FlowPropertyPageAbstract(NamedElementPropertyPage):
# fixme: unify ObjectFlowPropertyPage and ControlFlowPropertyPage
# after introducing common class for element editors
class ControlFlowPropertyPage(FlowPropertyPageAbstract):
component.adapts(UML.ControlFlow)
component.adapts(uml2.ControlFlow)
class ObjectFlowPropertyPage(FlowPropertyPageAbstract):
component.adapts(UML.ObjectFlow)
component.adapts(uml2.ObjectFlow)
component.provideAdapter(ControlFlowPropertyPage, name='Properties')

Some files were not shown because too many files have changed in this diff Show More