Welcome, guest | Sign In | My Account | Store | Cart

Notice! PyPM is being replaced with the ActiveState Platform, which enhances PyPM’s build and deploy capabilities. Create your free Platform account to download ActivePython or customize Python with the packages you require and get automatic updates.

Download
ActivePython
INSTALL>
pypm install stalker

How to install stalker

  1. Download and install ActivePython
  2. Open Command Prompt
  3. Type pypm install stalker
 Python 2.7Python 3.2Python 3.3
Windows (32-bit)
0.1.2.a3
0.2.0.rc5Never BuiltWhy not?
0.1.2.a3 Available View build log
0.1.1.a9 Available View build log
0.1.1.a6 Available View build log
0.1.1.a5 Available View build log
0.1.1.a2 Available View build log
0.1.1.a0 Available View build log
0.1.0 Available View build log
Windows (64-bit)
0.1.2.a3
0.2.0.rc5Never BuiltWhy not?
0.1.2.a3 Available View build log
0.1.1.a9 Available View build log
0.1.1.a6 Available View build log
0.1.1.a5 Available View build log
0.1.1.a2 Available View build log
0.1.1.a0 Available View build log
0.1.0 Available View build log
Mac OS X (10.5+)
0.1.2.a3
0.2.0.rc5Never BuiltWhy not?
0.1.2.a3 Available View build log
0.1.1.a9 Available View build log
0.1.1.a6 Available View build log
0.1.1.a5 Available View build log
0.1.1.a2 Available View build log
0.1.1.a0 Available View build log
0.1.0 Available View build log
Linux (32-bit)
0.1.2.a3
0.2.0.rc5Never BuiltWhy not?
0.1.2.a3 Available View build log
0.1.1.a9 Available View build log
0.1.1.a6 Available View build log
0.1.1.a5 Available View build log
0.1.1.a2 Available View build log
0.1.1.a0 Available View build log
0.1.0 Available View build log
Linux (64-bit)
0.2.0.rc5 Available View build log
0.1.2.a3 Available View build log
0.1.1.a9 Available View build log
0.1.1.a6 Available View build log
0.1.1.a5 Available View build log
0.1.1.a2 Available View build log
0.1.1.a0 Available View build log
0.1.0 Available View build log
 
Depended by
Lastest release
version 0.2.0.rc5 on Jan 9th, 2014

About

Stalker is an Open Source Production Asset Management (ProdAM) System designed specifically for Animation and VFX Studios but can be used for any kind of projects. Stalker is licensed under LGPL v2.1.

Features:
  • Designed for animation and VFX Studios.
  • Platform independent.
  • Default installation handles nearly all the asset and project management needs of an animation and vfx studio.
  • Customizable with configuration scripts.
  • Customizable object model (Stalker Object Model - SOM).
  • Uses TaskJuggler as the project planing and tracking backend.
  • Can be used with any kind of databases supported by SQLAlchemy.
  • Can be connected to all the major 3d animation packages like Maya, Houdini, Nuke, Softimage, Vue, Blender etc. and any application that has a Python API.
Stalker is build over these other OpenSource projects:
  • Python
  • SQLAlchemy and Alembic
  • Jinja2
  • TaskJuggler
Source

The latest development version is available in Google Project page of Stalker or can be directly cloned with the following command if you already have mercurial installed:

hg clone https://stalker.googlecode.com/hg/ stalker

Stalker Changes

0.2.0.rc5
  • Update: For a container task, Task.total_logged_seconds and Task.schedule_seconds attributes are now using the info of the child tasks. Also these attributes are cached to database, so instead of querying the child tasks all the time, the calculated data is cached and whenever a TimeLog is created or updated for a child task (which changes the total_logged_seconds for the child task) or the schedule_timing or schedule_unit attributes are updated, the cached values are updated on the parents. Allowing Stalker to display percent_complete info of a container task without loading any of its children.
  • New: Added Task.percent_complete attribute, which calculates the percent of completeness of the task based on the Task.total_logged_seconds and Task.schedule_seconds attributes.
  • Fix: Added TimeLog.__eq__() operator to more robustly check if the time logs are overlapping.
  • New: Added Project.percent_complete, Percent.total_logged_seconds and Project.schedule_seconds attributes.
  • Update: ScheduleMixin._validate_dates() does not set the date values anymore, it just return the calculated and validated start, end and duration values.
  • Update: Vacation now can be created without a user instance, effectively making the Vacation a Studio wide vacation, which applies to all users.
  • Update: Vacation.__strictly_typed__ is updated to False, so there is no need to create a Type instance to be able to create a Vacation.
  • New: Studio.vacations property now returns the Vacation instances which has now user.
  • Update: Task.start and Task.end values are no more read from children Tasks for a container task over and over again but calculated whenever the start and end values of a child task are changed or a new child is appended or removed.
  • Update: SimpleEntity.description validation routine doesn't convert the input to string anymore, but checks the given description value against being a string or unicode instance.
  • New: Added Ticket.summary field.
  • Fix: Fixed Link.extension, it is now accepting unicode.
0.2.0.rc4
  • New: Added a new attribute to Version class called latest_version which holds the latest version in the version queue.

  • New: To optimize the database connection times, stalker.db.setup() will not try to initialize the database every time it is called anymore. This leads a ~4x speed up in database connection setup. To initialize a newly created database please use:

    # for a newly created database
    from stalker import db
    db.setup() # connects to database
    db.init()  # fills some default values to be used with Stalker
    
    # for any subsequent access just use (don't need to call db.init())
    db.setup()
    
  • Update: Removed all __init_on_load() methods from all of the classes. It was causing SQLAlchemy to eagerly load relations, thus slowing down queries in certain cases (especially in Task.parent -> Task.children relation).

  • Fix: Fixed Vacation class tj3 format.

  • Fix: Studio.now attribute was not properly working when the Studio instance has been restored from database.

0.2.0.rc3
  • New: Added a new attribute to Task class called responsible.
  • Update: Removed Sequence.lead_id use Task.reponsible instead.
  • Update: Updated documentation to include documentation about Configuring Stalker with config.py.
  • Update: The duration argument in Task class is removed. It is somehow against the idea of having schedule_model and schedule_timing arguments (schedule_model='duration' is kind of the same).
  • Update: Updated task documentation.
0.2.0.rc2
  • New: Added Version.created_with attribute to track the environment or host program name that a particular Version instance is created with.
0.2.0.rc1
  • Update: Moved the Pyramid part of the system to another package called stalker_pyramid.
  • Fix: Fixed setup.py where importing stalker to get the __version__ variable causing problems.
0.2.0.b9
  • New: Added Version.latest_published_version and Version.is_latest_published_version().
  • Fix: Fixed Version.__eq__(), now Stalker correctly distinguishes different Version instances.
  • New: Added Repository.to_linux_path(), Repository.to_windows_path(), Repository.to_osx_path() and Repository.to_native_path() to the Repository class.
  • New: Added Repository.is_in_repo(path) which checks if the given path is in this repo.
0.2.0.b8
  • Update: Renamed Version.version_of attribute to Version.task.
  • Fix: Fixed Version.version_number where it was not possible to have a version number bigger than 2.
  • Fix: In db.setup() Ticket statuses are only created if there aren't any.
  • Fix: Added Vacation class to the registered class list in stalker.db.
0.2.0.b7
  • Update: Task.schedule_constraint is now reflected to the tjp file correctly.
  • Fix: check_circular_dependency() now checks if the entity and the other_entity are the same.
  • Fix: Task.to_tjp() now correctly add the dependent tasks of a container task.
  • Fix: Task.__eq__() now correctly considers the parent, depends, resources, start and end dates.
  • Update: Task.priority is now reflected in tjp file if it is different than the default value (500).
  • New:: Added a new class called Vacation to hold user vacations.
  • Update: Removed dependencies to pyramid.security.Allow and pyramid.security.Deny in couple of packages.
  • Update: Changed the way the stalker.defaults is created.
  • Fix: EnvironmentBase.get_version_from_full_path(), EnvironmentBase.get_versions_from_path(), EnvironmentBase.trim_repo_path(), EnvironmentBase.find_repo methods are now working properly.
  • Update: Added Version.absolute_full_path property which renders the absolute full path which also includes the repository path.
  • Update: Added Version.absolute_path property which renders the absolute path which also includes the repository path.
0.2.0.b6
  • Fix: Fixed LocalSession._write_data(), previously it was not creating the local session folder.
  • New: Added a new method called LocalSession.delete() to remove the local session file.
  • Update: Link.full_path can now be set to an empty string. This is updated in this way for Version class.
  • Update: Updated the formatting of SimpleEntity.nice_name, it is now possible to have uppercase letters and camel case format will be preserved.
  • Update: Version.take_name formatting is enhanced.
  • New: Task class is now mixed in with ReferenceMixin making it unnecessary to have Asset, Shot and Sequence classes all mixed in individually. Thus removed the ReferenceMixin from Asset, Shot and Sequence classes.
  • Update: Added Task.schedule_model validation and its tests.
  • New: Added ScheduleMixin.total_seconds and ScheduleMixin.computed_total_seconds.
0.2.0.b5
  • New: Version class now has two new attributes called parent and children which will be used in tracking of the history of Version instances and track which Versions are derived from which Version.
  • New: Versions instances are now derived from Link class and not Entity.
  • Update: Added new revisions to alembic to reflect the change in Versions table.
  • Update: Links.path is renamed to Links.full_path and added three new attributes called path, filename and extension.
  • Update: Added new revisions to alembic to reflect the change in Links table.
  • New: Added a new class called LocalSession to store session data in users local filesystem. It is going to be replaced with some other system like Beaker.
  • Fix: Database part of Stalker can now be imported without depending to Pyramid.
  • Fix: Fixed documentation errors that Sphinx complained about.
0.2.0.b4
  • No changes in SOM.
0.2.0.b3
  • Update: FilenameTemplate's are not strictly typed anymore.
  • Update: Removed the FilenameTemplate type initialization, FilenameTemplates do not depend on Types anymore.
  • Update: Added back the plural_class_name (previously plural_name) property to the ORMClass class, so all the classes in SOM now have this new property.
  • Update: Added accepts_references attribute to the EntityType class.
  • New: The Link class has a new attribute called original_filename to store the original file names of link files.
  • New: Added alembic to the project requirements.
  • New: Added alembic migrations which adds the accepts_references column to EntityTypes table and original_name to the Links table.
0.2.0.b2
  • Stalker is now compatible with Python 2.6.
  • Task:
    • Update: Tasks now have a new attribute called watchers which holds a list of User instances watching the particular Task.
    • Update: Users now have a new attribute called watching which is a list of Task instances that this user is watching.
  • TimeLog:
    • Update: TimeLog instances will expand Task.schedule_timing value automatically if the total amount of logged time is more than the schedule_timing value.
    • Update: TimeLogs are now considered while scheduling the task.
    • Fix: TimeLogs raises OverBookedError when appending the same TimeLog instance to the same resource.
  • Auth:
    • Fix: The default ACLs for determining the permissions are now working properly.
0.2.0.b1
  • WorkingHours.is_working_hour() is working now.
  • WorkingHours class is moved from stalker.models.project to stalker.models.studio module.
  • daily_working_hours attribute is moved from stalker.models.project.Project to stalker.models.studio.Studio class.
  • Repository path variables now ends with a forward slash even if it is not given.
  • Updated Project classes validation messages to correlate with Stalker standard.
  • Implementation of the Studio class is finished. The scheduling works like a charm.
  • It is now possible to use any characters in SimpleEntity.name and the derived classes.
  • Booking class is renamed to TimeLog.
0.2.0.a10
  • Added new attribute to WorkingHours class called weekly_working_hours, which calculates the weekly working hours based on the working hours defined in the instance.

  • Task class now has a new attribute called schedule_timing which is replacing the effort, length and duration attributes. Together with the schedule_model attribute it will be used in scheduling the Task.

  • Updated the config system to the one used in oyProjectManager (based on Sphinx config system). Now to reach the defaults:

    # instead of doing the following
    from stalker.conf import defaults # not valid anymore
    
    # use this
    from stalker import defaults
    

    If the above idiom is used, the old defaults module behaviour is retained, so no code change is required other than the new lower case config variable names.

0.2.0.a9
  • A new property called to_tjp added to the SimpleEntity class which needs to be implemented in the child and is going to be used in TaskJuggler integration.
  • A new attribute called is_scheduled added to Task class and it is going to be used in Gantt charts. Where it will lock the class and will not try to snap it to anywhere if it is scheduled.
  • Changed the resolution attribute name to timing_resolution to comply with TaskJuggler.
  • ScheduleMixin:
    • Updated ScheduleMixin class documentation.
    • There are two new read-only attributes called computed_start and computed_end. These attributes will be used in storing of the values calculated by TaskJuggler, and will be used in Gantt Charts if available.
    • Added computed_duration.
  • Task:
    • Arranged the TaskJuggler workflow.
    • The task will use the effort > length > duration attributes in to_tjp property.
  • Changed the license of Stalker from BSD-2 to LGPL 2.1. Any version previous to 0.2.0.a9 will be still BSD-2 and any version from and including 0.2.0.a9 will be distributed under LGPL 2.1 license.
  • Added new types of classes called Schedulers which are going to be used in scheduling the tasks.
  • Added TaskJugglerScheduler, it uses the given project and schedules its tasks.
0.2.0.a8
  • TagSelect now can be filled by setting its value attribute (Ex: TagSelect.set('value', data))
  • Added a new method called is_root to Task class. It is true for tasks where there are no parents.
  • Added a new attribute called users to the Department class which is a synonym for the members attribute.
  • Task:
    • Task class is now preventing one of the dependents to be set as the parent of a task.
    • Task class is now preventing one of the parents to be set as the one of the dependents of a task.
    • Fixed autoflush bugs in Task class.
  • Fixed admin users department initialization.
  • Added thumbnail attribute to the SimpleEntity class which is a reference to a Link instance, showing the path of the thumbnail.
  • Fixed Circular Dependency bug in Task class, where a parent of a newly created task is depending to another task which is set as the dependee for this newly created task (T1 -> T3 -> T2 -> T1 (parent relation) -> T3 -> T2 etc.).
0.2.0.a7
  • Changed these default setting value names to corresponding new names:

    • DEFAULT_TASK_DURATION -> TASK_DURATION
    • DEFAULT_TASK_PRIORITY -> TASK_PRIORITY
    • DEFAULT_VERSION_TAKE_NAME -> VERSION_TAKE_NAME
    • DEFAULT_TICKET_LABEL -> TICKET_LABEL
    • DEFAULT_ACTIONS -> ACTIONS
    • DEFAULT_BG_COLOR -> BG_COLOR
    • DEFAULT_FG_COLOR -> FG_COLOR
  • stalker.conf.defaults:

    • Added default settings for project working hours (WORKING_HOURS, DAY_ORDER, DAILY_WORKING_HOURS)
    • Added a new variable for setting the task time resolution called TIME_RESOLUTION.
  • stalker.models.project.Project:

    • Removed Project.project_tasks attribute, use Project.tasks directly to get all the Tasks in that project. For root task you can do a quick query:

      Task.query.filter(Task.project==proj_id).filter(Task.parent==None).all()
      

      This will also return the Assets, Sequences and Shots in that project, which are also Tasks.

    • Users are now assigned to Projects by appending them to the Project.users list. This is done in this way to allow a reduced list of resources to be shown in the Task creation dialogs.

    • Added a new helper class for Project working hour management, called WorkingHours.

    • Added a new attribute to Project class called working_hours which holds stalker.models.project.WorkingHours instances to manage the Project working hours. It will directly be passed to TaskJuggler.

  • stalker.models.task.Task:

    • Removed the Task.task_of attribute, use Task.parent to get the owner of this Task.
    • Task now has two new attributes called Task.parent and Task.children which allow more complex Task-to-Task relation.
    • Secondary table name for holding Task to Task dependency relation is renamed from Task_Tasks to Task_Dependencies.
    • check_circular_dependency function is now accepting a third argument which is the name of the attribute to be investigated for circular relationship. It is done in that way to be able to use the same function in searching for circular relations both in parent/child and depender/dependee relations.
  • ScheduleMixin:

    • Added a new attribute to ScheduleMixin for time resolution adjustment. Default value is 1 hour and can be set with stalker.conf.defaults.TIME_RESOLUTION. Any finer time than the resolution is rounded to the closest multiply of the resolution. It is possible to set it from microseconds to years. Although 1 hour is a very reasonable resolution which is also the default resolution for TaskJuggler.
    • ScheduleMixin now uses datetime.datetime for the start and end attributes.
    • Renamed the start_date attribute to start.
    • Renamed the end_date attribute to end
  • Removed the TaskableEntity.

  • Asset, Sequence and Shot classes are now derived from Task class allowing more complex Task relation combined with the new parent/child relation of Tasks. Use Asset.children or Asset.tasks to reach the child tasks of that asset (same with Sequence and Shot classes).

  • stalker.models.shot.Shot:

    • Removed the sequence and introduced sequences attribute in Shot class. Now one shot can be in more than one Sequence. Allowing more complex Shot/Sequence relations..
    • Shots can now be created without a Sequence instance. The sequence attribute is just used to group the Shots.
    • Shots now have a new attribute called scenes, holding Scene instances. It is created to group same shots occurring in the same scenes.
  • In tests all the Warnings are now properly handled as Warnings.

  • stalker.models.ticket.Ticket:

    • Ticket instances are now tied to Projects and it is now possible to create Tickets without supplying a Version. They are free now.
    • It is now possible to link any SimpleEntity to a Ticket.
    • The Ticket Workflow is now fully customizable. Use stalker.conf.defaults.TICKET_WORKFLOW dictionary to define the workflow and stalker.conf.defaults.TICKET_STATUS_ORDER for the order of the ticket statuses.
  • Added a new class called Scene to manage Shots with another property.

  • Removed the output_path attribute in FilenameTemplate class.

  • Grouped the templates for each entity under a directory with the entity name.

0.2.0.a6
  • Users now can have more than one Department.
  • User instances now have two new properties for getting the user tickets (User.tickets) and the open tickets (User.open_tickets).
  • New shortcut Task.project returns the Task.task_of.project value.
  • Shot and Asset creation dialogs now automatically updated with the given Project instance info.
  • User overview page is now reflection the new design.
0.2.0.a5
  • The code attribute of the SimpleEntity is now introduced as a separate mixin. To let it be used by the classes it is really needed.

  • The query method is now converted to a property so it is now possible to use it like a property as in the SQLAlchemy.orm.Session as shown below:

    from stalker import Project
    Project.query.all() # instead of Project.query().all()
    
  • ScheduleMixin.due_date is renamed to ScheduleMixin.end_date.

  • Added a new class attribute to SimpleEntity called __auto_name__ which controls the naming of the instances and instances derived from SimpleEntity. If __auto_name__ is set to True the name attribute of the instance will be automatically generated and it will have the following format:

    {{ClassName}}_{{UUID4}}
    

    Here are a couple of naming examples:

    Ticket_74bb46b0-29de-4f3e-b4e6-8bcf6aed352d
    Version_2fa5749e-8cdb-4887-aef2-6d8cec6a4faa
    
  • Fixed an autoflush issue with SQLAlchemy in StatusList class. Now the status column is again not nullable in StatusMixin.

0.2.0.a4
  • Added a new class called EntityType to hold all the available class names and capabilities.

  • Version class now has a new attribute called inputs to hold the inputs of the current Version instance. It is a list of Link instances.

  • FilenameTemplate classes path and filename attributes are no more converted to string, so given a non string value will raise TypeError.

  • Structure.custom_template now only accepts strings and None, setting it to anything else will raise a TypeError.

  • Two Type's for FilenameTemplate's are created by default when initializing the database, first is called "Version" and it is used to define FilenameTemplates which are used for placing Version source files. The second one is called "Reference" and it is used when injecting references to a given class. Along with the FilenameTemplate.target_entity_type this will allow one to create two different FilenameTemplates for one class:

    # first get the Types
    vers_type = Type.query()\
                .filter_by(target_entity_type="FilenameTemplate")\
                .filter_by(type="Version")\
                .first()
    
    ref_type = Type.query()\
               .filter_by(target_entity_type="FilenameTemplate")\
               .filter_by(type="Reference")\
               .first()
    
    # lets create a FilenameTemplate for placing Asset Version files.
    f_ver = FilenameTemplate(
        target_entity_type="Asset",
        type=vers_type,
        path="Assets/{{asset.type.code}}/{{asset.code}}/{{task.type.code}}",
        filename="{{asset.code}}_{{version.take_name}}_{{task.type.code}}_v{{'%03d'|version.version_number}}{{link.extension}}"
        output_path="{{version.path}}/Outputs/{{version.take_name}}"
    )
    
    # and now define a FilenameTemplate for placing Asset Reference files.
    # no need to have an output_path here...
    f_ref = FilenameTemplate(
        target_entity_type="Asset",
        type=ref_type,
        path="Assets/{{asset.type.code}}/{{asset.code}}/References",
        filename="{{link.type.code}}/{{link.id}}{{link.extension}}"
    )
    
  • stalker.db.register() now accepts only real classes instead of class names. This way it can store more information about classes.

  • Status.bg_color and Status.fg_color attributes are now simple integers. And the Color class is removed.

  • StatusMixin.status is now a ForeignKey to a the Statuses table, thus it is a real Status instance instead of an integer showing the index of the Status in the related StatusList. This way the Status of the object will not change if the content of the StatusList is changed.

  • Added new attribute Project.project_tasks which holds all the direct or indirect Tasks created for that project.

  • User.login_name is renamed to User.login.

  • Removed the first_name, last_name and initials attributes from User class. Now the name and code attributes are going to be used, thus the name attribute is no more the equivalent of login and the code attribute is doing what was initials doing previously.

0.2.0.a3
  • Status class now has two new attributes bg_color and fg_color to hold the UI colors of the Status instance. The colors are Color instances.
0.2.0.a2
  • SimpleEntity now has an attribute called generic_data which can hold any kind of SOM object inside and it is a list.

  • Changed the formatting rules for the name in SimpleEntity class, now it can start with a number, and it is not allowed to have multiple whitespace characters following each other.

  • The source attribute in Version is renamed to source_file.

  • The version attribute in Version is renamed to version_number.

  • The take attribute in Version is renamed to take_name.

  • The version_number in Version is now generated automatically if it is skipped or given as None or it is too low where there is already a version number for the same Version series (means attached to the same Task and has the same take_name.

  • Moved the User class to stalker.models.auth module.

  • Removed the stalker.ext.auth module because it is not necessary anymore. Thus the User now handles all the password conversions by itself.

  • PermissionGroup is renamed back to Group again to match with the general naming of the authorization concept.

  • Created two new classes for the Authorization system, first one is called Permission and the second one is a Mixin which is called ACLMixin which adds ACLs to the mixed in class. For now, only the User and Group classes are mixed with this mixin by default.

  • The declarative Base class of SQLAlchemy is now created by binding it to a ORMClass (a random name) which lets all the derived class to have a method called query which will bypass the need of calling DBSession.query(class_) but instead just call class_.query():

    from stalker.models.auth import User
    user_1 = User.query().filter_by(name='a user name').first()
    
0.2.0.a1
  • Changed the db.setup arguments. It is now accepting a dictionary instead of just a string to comply with the SQLAlchemy scaffold and this dictionary should contain keys for the SQLAlchemy engine setup. There is another utility that comes with Pyramid to setup the database under the scripts folder, it is also working without any problem with stalker.db.

  • The session variable is renamed to DBSession and is now a scopped session, so there is no need to use DBSession.commit it will be handled by the system it self.

  • Even though the DBSession is using the Zope Transaction Manager extension normally, in the database tests no extension is used because the transaction manager was swallowing all errors and it was a little weird to try to catch this errors out of the with block.

  • Refactored the code, all the models are now in separate python files, but can be directly imported from the main stalker module as shown:

    from stalker import User, Department, Task
    

    By using this kind of organization, both development and usage will be eased out.

  • task_of now only accepts TaskableEntity instances.

  • Updated the examples. It is now showing how to extend SOM correctly.

  • Updated the references to the SOM classes in docstrings and rst files.

  • Removed the Review class. And introduced the much handier Ticket class. Now reviewing a data is the process of creating Ticket's to that data.

  • The database is now initialized with a StatusList and a couple of Statuses appropriate for Ticket instances.

  • The database is now initialized with two Type instances ('Enhancement' and 'Defect') suitable for Ticket instances.

  • StatusMixin now stores the status attribute as an Integer showing the index of the Status in the status_list attribute but when asked for the value of StatusMixin.status attribute it will return a proper Status instance and the attribute can be set with an integer or with a proper Status instance.

Subscribe to package updates

Last updated Jan 9th, 2014

Download Stats

Last month:1

What does the lock icon mean?

Builds marked with a lock icon are only available via PyPM to users with a current ActivePython Business Edition subscription.

Need custom builds or support?

ActivePython Enterprise Edition guarantees priority access to technical support, indemnification, expert consulting and quality-assured language builds.

Plan on re-distributing ActivePython?

Get re-distribution rights and eliminate legal risks with ActivePython OEM Edition.